1ffeaf689SAlexander Kabaev // Debugging map implementation -*- C++ -*- 2ffeaf689SAlexander Kabaev 3*f8a1b7d9SAlexander Kabaev // Copyright (C) 2003, 2004, 2005 4ffeaf689SAlexander Kabaev // Free Software Foundation, Inc. 5ffeaf689SAlexander Kabaev // 6ffeaf689SAlexander Kabaev // This file is part of the GNU ISO C++ Library. This library is free 7ffeaf689SAlexander Kabaev // software; you can redistribute it and/or modify it under the 8ffeaf689SAlexander Kabaev // terms of the GNU General Public License as published by the 9ffeaf689SAlexander Kabaev // Free Software Foundation; either version 2, or (at your option) 10ffeaf689SAlexander Kabaev // any later version. 11ffeaf689SAlexander Kabaev 12ffeaf689SAlexander Kabaev // This library is distributed in the hope that it will be useful, 13ffeaf689SAlexander Kabaev // but WITHOUT ANY WARRANTY; without even the implied warranty of 14ffeaf689SAlexander Kabaev // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 15ffeaf689SAlexander Kabaev // GNU General Public License for more details. 16ffeaf689SAlexander Kabaev 17ffeaf689SAlexander Kabaev // You should have received a copy of the GNU General Public License along 18ffeaf689SAlexander Kabaev // with this library; see the file COPYING. If not, write to the Free 19*f8a1b7d9SAlexander Kabaev // Software Foundation, 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, 20ffeaf689SAlexander Kabaev // USA. 21ffeaf689SAlexander Kabaev 22ffeaf689SAlexander Kabaev // As a special exception, you may use this file as part of a free software 23ffeaf689SAlexander Kabaev // library without restriction. Specifically, if other files instantiate 24ffeaf689SAlexander Kabaev // templates or use macros or inline functions from this file, or you compile 25ffeaf689SAlexander Kabaev // this file and link it with other files to produce an executable, this 26ffeaf689SAlexander Kabaev // file does not by itself cause the resulting executable to be covered by 27ffeaf689SAlexander Kabaev // the GNU General Public License. This exception does not however 28ffeaf689SAlexander Kabaev // invalidate any other reasons why the executable file might be covered by 29ffeaf689SAlexander Kabaev // the GNU General Public License. 30ffeaf689SAlexander Kabaev 31*f8a1b7d9SAlexander Kabaev /** @file debug/map.h 32*f8a1b7d9SAlexander Kabaev * This file is a GNU debug extension to the Standard C++ Library. 33*f8a1b7d9SAlexander Kabaev */ 34*f8a1b7d9SAlexander Kabaev 35ffeaf689SAlexander Kabaev #ifndef _GLIBCXX_DEBUG_MAP_H 36ffeaf689SAlexander Kabaev #define _GLIBCXX_DEBUG_MAP_H 1 37ffeaf689SAlexander Kabaev 38ffeaf689SAlexander Kabaev #include <debug/safe_sequence.h> 39ffeaf689SAlexander Kabaev #include <debug/safe_iterator.h> 40ffeaf689SAlexander Kabaev #include <utility> 41ffeaf689SAlexander Kabaev 42*f8a1b7d9SAlexander Kabaev namespace std 43*f8a1b7d9SAlexander Kabaev { 44*f8a1b7d9SAlexander Kabaev namespace __debug 45ffeaf689SAlexander Kabaev { 46ffeaf689SAlexander Kabaev template<typename _Key, typename _Tp, typename _Compare = std::less<_Key>, 47ffeaf689SAlexander Kabaev typename _Allocator = std::allocator<std::pair<const _Key, _Tp> > > 48ffeaf689SAlexander Kabaev class map 49ffeaf689SAlexander Kabaev : public _GLIBCXX_STD::map<_Key, _Tp, _Compare, _Allocator>, 50ffeaf689SAlexander Kabaev public __gnu_debug::_Safe_sequence<map<_Key, _Tp, _Compare, _Allocator> > 51ffeaf689SAlexander Kabaev { 52ffeaf689SAlexander Kabaev typedef _GLIBCXX_STD::map<_Key, _Tp, _Compare, _Allocator> _Base; 53ffeaf689SAlexander Kabaev typedef __gnu_debug::_Safe_sequence<map> _Safe_base; 54ffeaf689SAlexander Kabaev 55ffeaf689SAlexander Kabaev public: 56ffeaf689SAlexander Kabaev // types: 57ffeaf689SAlexander Kabaev typedef _Key key_type; 58ffeaf689SAlexander Kabaev typedef _Tp mapped_type; 59ffeaf689SAlexander Kabaev typedef std::pair<const _Key, _Tp> value_type; 60ffeaf689SAlexander Kabaev typedef _Compare key_compare; 61ffeaf689SAlexander Kabaev typedef _Allocator allocator_type; 62*f8a1b7d9SAlexander Kabaev typedef typename _Base::reference reference; 63*f8a1b7d9SAlexander Kabaev typedef typename _Base::const_reference const_reference; 64ffeaf689SAlexander Kabaev 65ffeaf689SAlexander Kabaev typedef __gnu_debug::_Safe_iterator<typename _Base::iterator, map> 66ffeaf689SAlexander Kabaev iterator; 67ffeaf689SAlexander Kabaev typedef __gnu_debug::_Safe_iterator<typename _Base::const_iterator, map> 68ffeaf689SAlexander Kabaev const_iterator; 69ffeaf689SAlexander Kabaev 70ffeaf689SAlexander Kabaev typedef typename _Base::size_type size_type; 71ffeaf689SAlexander Kabaev typedef typename _Base::difference_type difference_type; 72*f8a1b7d9SAlexander Kabaev typedef typename _Base::pointer pointer; 73*f8a1b7d9SAlexander Kabaev typedef typename _Base::const_pointer const_pointer; 74ffeaf689SAlexander Kabaev typedef std::reverse_iterator<iterator> reverse_iterator; 75ffeaf689SAlexander Kabaev typedef std::reverse_iterator<const_iterator> const_reverse_iterator; 76ffeaf689SAlexander Kabaev 77ffeaf689SAlexander Kabaev // 23.3.1.1 construct/copy/destroy: 78ffeaf689SAlexander Kabaev explicit map(const _Compare& __comp = _Compare(), 79ffeaf689SAlexander Kabaev const _Allocator& __a = _Allocator()) _Base(__comp,__a)80ffeaf689SAlexander Kabaev : _Base(__comp, __a) { } 81ffeaf689SAlexander Kabaev 82ffeaf689SAlexander Kabaev template<typename _InputIterator> 83ffeaf689SAlexander Kabaev map(_InputIterator __first, _InputIterator __last, 84ffeaf689SAlexander Kabaev const _Compare& __comp = _Compare(), 85ffeaf689SAlexander Kabaev const _Allocator& __a = _Allocator()) _Base(__gnu_debug::__check_valid_range (__first,__last),__last,__comp,__a)86ffeaf689SAlexander Kabaev : _Base(__gnu_debug::__check_valid_range(__first, __last), __last, 87ffeaf689SAlexander Kabaev __comp, __a), _Safe_base() { } 88ffeaf689SAlexander Kabaev map(const map<_Key,_Tp,_Compare,_Allocator> & __x)89ffeaf689SAlexander Kabaev map(const map<_Key,_Tp,_Compare,_Allocator>& __x) 90ffeaf689SAlexander Kabaev : _Base(__x), _Safe_base() { } 91ffeaf689SAlexander Kabaev map(const _Base & __x)92ffeaf689SAlexander Kabaev map(const _Base& __x) : _Base(__x), _Safe_base() { } 93ffeaf689SAlexander Kabaev ~map()94ffeaf689SAlexander Kabaev ~map() { } 95ffeaf689SAlexander Kabaev 96ffeaf689SAlexander Kabaev map<_Key,_Tp,_Compare,_Allocator>& 97ffeaf689SAlexander Kabaev operator=(const map<_Key,_Tp,_Compare,_Allocator>& __x) 98ffeaf689SAlexander Kabaev { 99ffeaf689SAlexander Kabaev *static_cast<_Base*>(this) = __x; 100ffeaf689SAlexander Kabaev this->_M_invalidate_all(); 101ffeaf689SAlexander Kabaev return *this; 102ffeaf689SAlexander Kabaev } 103ffeaf689SAlexander Kabaev 104ffeaf689SAlexander Kabaev // _GLIBCXX_RESOLVE_LIB_DEFECTS 105ffeaf689SAlexander Kabaev // 133. map missing get_allocator() 106ffeaf689SAlexander Kabaev using _Base::get_allocator; 107ffeaf689SAlexander Kabaev 108ffeaf689SAlexander Kabaev // iterators: 109ffeaf689SAlexander Kabaev iterator begin()110ffeaf689SAlexander Kabaev begin() 111ffeaf689SAlexander Kabaev { return iterator(_Base::begin(), this); } 112ffeaf689SAlexander Kabaev 113ffeaf689SAlexander Kabaev const_iterator begin()114ffeaf689SAlexander Kabaev begin() const 115ffeaf689SAlexander Kabaev { return const_iterator(_Base::begin(), this); } 116ffeaf689SAlexander Kabaev 117ffeaf689SAlexander Kabaev iterator end()118ffeaf689SAlexander Kabaev end() 119ffeaf689SAlexander Kabaev { return iterator(_Base::end(), this); } 120ffeaf689SAlexander Kabaev 121ffeaf689SAlexander Kabaev const_iterator end()122ffeaf689SAlexander Kabaev end() const 123ffeaf689SAlexander Kabaev { return const_iterator(_Base::end(), this); } 124ffeaf689SAlexander Kabaev 125ffeaf689SAlexander Kabaev reverse_iterator rbegin()126ffeaf689SAlexander Kabaev rbegin() 127ffeaf689SAlexander Kabaev { return reverse_iterator(end()); } 128ffeaf689SAlexander Kabaev 129ffeaf689SAlexander Kabaev const_reverse_iterator rbegin()130ffeaf689SAlexander Kabaev rbegin() const 131ffeaf689SAlexander Kabaev { return const_reverse_iterator(end()); } 132ffeaf689SAlexander Kabaev 133ffeaf689SAlexander Kabaev reverse_iterator rend()134ffeaf689SAlexander Kabaev rend() 135ffeaf689SAlexander Kabaev { return reverse_iterator(begin()); } 136ffeaf689SAlexander Kabaev 137ffeaf689SAlexander Kabaev const_reverse_iterator rend()138ffeaf689SAlexander Kabaev rend() const 139ffeaf689SAlexander Kabaev { return const_reverse_iterator(begin()); } 140ffeaf689SAlexander Kabaev 141ffeaf689SAlexander Kabaev // capacity: 142ffeaf689SAlexander Kabaev using _Base::empty; 143ffeaf689SAlexander Kabaev using _Base::size; 144ffeaf689SAlexander Kabaev using _Base::max_size; 145ffeaf689SAlexander Kabaev 146ffeaf689SAlexander Kabaev // 23.3.1.2 element access: 147ffeaf689SAlexander Kabaev using _Base::operator[]; 148ffeaf689SAlexander Kabaev 149*f8a1b7d9SAlexander Kabaev // _GLIBCXX_RESOLVE_LIB_DEFECTS 150*f8a1b7d9SAlexander Kabaev // DR 464. Suggestion for new member functions in standard containers. 151*f8a1b7d9SAlexander Kabaev using _Base::at; 152*f8a1b7d9SAlexander Kabaev 153ffeaf689SAlexander Kabaev // modifiers: 154ffeaf689SAlexander Kabaev std::pair<iterator, bool> insert(const value_type & __x)155ffeaf689SAlexander Kabaev insert(const value_type& __x) 156ffeaf689SAlexander Kabaev { 157ffeaf689SAlexander Kabaev typedef typename _Base::iterator _Base_iterator; 158ffeaf689SAlexander Kabaev std::pair<_Base_iterator, bool> __res = _Base::insert(__x); 159ffeaf689SAlexander Kabaev return std::pair<iterator, bool>(iterator(__res.first, this), 160ffeaf689SAlexander Kabaev __res.second); 161ffeaf689SAlexander Kabaev } 162ffeaf689SAlexander Kabaev 163ffeaf689SAlexander Kabaev iterator insert(iterator __position,const value_type & __x)164ffeaf689SAlexander Kabaev insert(iterator __position, const value_type& __x) 165ffeaf689SAlexander Kabaev { 166ffeaf689SAlexander Kabaev __glibcxx_check_insert(__position); 167ffeaf689SAlexander Kabaev return iterator(_Base::insert(__position.base(), __x), this); 168ffeaf689SAlexander Kabaev } 169ffeaf689SAlexander Kabaev 170ffeaf689SAlexander Kabaev template<typename _InputIterator> 171ffeaf689SAlexander Kabaev void insert(_InputIterator __first,_InputIterator __last)172ffeaf689SAlexander Kabaev insert(_InputIterator __first, _InputIterator __last) 173ffeaf689SAlexander Kabaev { 174f260e61bSAlexander Kabaev __glibcxx_check_valid_range(__first, __last); 175ffeaf689SAlexander Kabaev _Base::insert(__first, __last); 176ffeaf689SAlexander Kabaev } 177ffeaf689SAlexander Kabaev 178ffeaf689SAlexander Kabaev void erase(iterator __position)179ffeaf689SAlexander Kabaev erase(iterator __position) 180ffeaf689SAlexander Kabaev { 181ffeaf689SAlexander Kabaev __glibcxx_check_erase(__position); 182ffeaf689SAlexander Kabaev __position._M_invalidate(); 183ffeaf689SAlexander Kabaev _Base::erase(__position.base()); 184ffeaf689SAlexander Kabaev } 185ffeaf689SAlexander Kabaev 186ffeaf689SAlexander Kabaev size_type erase(const key_type & __x)187ffeaf689SAlexander Kabaev erase(const key_type& __x) 188ffeaf689SAlexander Kabaev { 189ffeaf689SAlexander Kabaev iterator __victim = find(__x); 190ffeaf689SAlexander Kabaev if (__victim == end()) 191ffeaf689SAlexander Kabaev return 0; 192ffeaf689SAlexander Kabaev else 193ffeaf689SAlexander Kabaev { 194ffeaf689SAlexander Kabaev __victim._M_invalidate(); 195ffeaf689SAlexander Kabaev _Base::erase(__victim.base()); 196ffeaf689SAlexander Kabaev return 1; 197ffeaf689SAlexander Kabaev } 198ffeaf689SAlexander Kabaev } 199ffeaf689SAlexander Kabaev 200ffeaf689SAlexander Kabaev void erase(iterator __first,iterator __last)201ffeaf689SAlexander Kabaev erase(iterator __first, iterator __last) 202ffeaf689SAlexander Kabaev { 203ffeaf689SAlexander Kabaev // _GLIBCXX_RESOLVE_LIB_DEFECTS 204ffeaf689SAlexander Kabaev // 151. can't currently clear() empty container 205ffeaf689SAlexander Kabaev __glibcxx_check_erase_range(__first, __last); 206ffeaf689SAlexander Kabaev while (__first != __last) 207ffeaf689SAlexander Kabaev this->erase(__first++); 208ffeaf689SAlexander Kabaev } 209ffeaf689SAlexander Kabaev 210ffeaf689SAlexander Kabaev void swap(map<_Key,_Tp,_Compare,_Allocator> & __x)211ffeaf689SAlexander Kabaev swap(map<_Key,_Tp,_Compare,_Allocator>& __x) 212ffeaf689SAlexander Kabaev { 213ffeaf689SAlexander Kabaev _Base::swap(__x); 214ffeaf689SAlexander Kabaev this->_M_swap(__x); 215ffeaf689SAlexander Kabaev } 216ffeaf689SAlexander Kabaev 217ffeaf689SAlexander Kabaev void clear()218ffeaf689SAlexander Kabaev clear() 219ffeaf689SAlexander Kabaev { this->erase(begin(), end()); } 220ffeaf689SAlexander Kabaev 221ffeaf689SAlexander Kabaev // observers: 222ffeaf689SAlexander Kabaev using _Base::key_comp; 223ffeaf689SAlexander Kabaev using _Base::value_comp; 224ffeaf689SAlexander Kabaev 225ffeaf689SAlexander Kabaev // 23.3.1.3 map operations: 226ffeaf689SAlexander Kabaev iterator find(const key_type & __x)227ffeaf689SAlexander Kabaev find(const key_type& __x) 228ffeaf689SAlexander Kabaev { return iterator(_Base::find(__x), this); } 229ffeaf689SAlexander Kabaev 230ffeaf689SAlexander Kabaev const_iterator find(const key_type & __x)231ffeaf689SAlexander Kabaev find(const key_type& __x) const 232ffeaf689SAlexander Kabaev { return const_iterator(_Base::find(__x), this); } 233ffeaf689SAlexander Kabaev 234ffeaf689SAlexander Kabaev using _Base::count; 235ffeaf689SAlexander Kabaev 236ffeaf689SAlexander Kabaev iterator lower_bound(const key_type & __x)237ffeaf689SAlexander Kabaev lower_bound(const key_type& __x) 238ffeaf689SAlexander Kabaev { return iterator(_Base::lower_bound(__x), this); } 239ffeaf689SAlexander Kabaev 240ffeaf689SAlexander Kabaev const_iterator lower_bound(const key_type & __x)241ffeaf689SAlexander Kabaev lower_bound(const key_type& __x) const 242ffeaf689SAlexander Kabaev { return const_iterator(_Base::lower_bound(__x), this); } 243ffeaf689SAlexander Kabaev 244ffeaf689SAlexander Kabaev iterator upper_bound(const key_type & __x)245ffeaf689SAlexander Kabaev upper_bound(const key_type& __x) 246ffeaf689SAlexander Kabaev { return iterator(_Base::upper_bound(__x), this); } 247ffeaf689SAlexander Kabaev 248ffeaf689SAlexander Kabaev const_iterator upper_bound(const key_type & __x)249ffeaf689SAlexander Kabaev upper_bound(const key_type& __x) const 250ffeaf689SAlexander Kabaev { return const_iterator(_Base::upper_bound(__x), this); } 251ffeaf689SAlexander Kabaev 252ffeaf689SAlexander Kabaev std::pair<iterator,iterator> equal_range(const key_type & __x)253ffeaf689SAlexander Kabaev equal_range(const key_type& __x) 254ffeaf689SAlexander Kabaev { 255ffeaf689SAlexander Kabaev typedef typename _Base::iterator _Base_iterator; 256ffeaf689SAlexander Kabaev std::pair<_Base_iterator, _Base_iterator> __res = 257ffeaf689SAlexander Kabaev _Base::equal_range(__x); 258ffeaf689SAlexander Kabaev return std::make_pair(iterator(__res.first, this), 259ffeaf689SAlexander Kabaev iterator(__res.second, this)); 260ffeaf689SAlexander Kabaev } 261ffeaf689SAlexander Kabaev 262ffeaf689SAlexander Kabaev std::pair<const_iterator,const_iterator> equal_range(const key_type & __x)263ffeaf689SAlexander Kabaev equal_range(const key_type& __x) const 264ffeaf689SAlexander Kabaev { 265ffeaf689SAlexander Kabaev typedef typename _Base::const_iterator _Base_const_iterator; 266ffeaf689SAlexander Kabaev std::pair<_Base_const_iterator, _Base_const_iterator> __res = 267ffeaf689SAlexander Kabaev _Base::equal_range(__x); 268ffeaf689SAlexander Kabaev return std::make_pair(const_iterator(__res.first, this), 269ffeaf689SAlexander Kabaev const_iterator(__res.second, this)); 270ffeaf689SAlexander Kabaev } 271ffeaf689SAlexander Kabaev 272ffeaf689SAlexander Kabaev _Base& _M_base()273ffeaf689SAlexander Kabaev _M_base() { return *this; } 274ffeaf689SAlexander Kabaev 275ffeaf689SAlexander Kabaev const _Base& _M_base()276ffeaf689SAlexander Kabaev _M_base() const { return *this; } 277ffeaf689SAlexander Kabaev 278ffeaf689SAlexander Kabaev private: 279ffeaf689SAlexander Kabaev void _M_invalidate_all()280ffeaf689SAlexander Kabaev _M_invalidate_all() 281ffeaf689SAlexander Kabaev { 282ffeaf689SAlexander Kabaev typedef typename _Base::const_iterator _Base_const_iterator; 283ffeaf689SAlexander Kabaev typedef __gnu_debug::_Not_equal_to<_Base_const_iterator> _Not_equal; 284ffeaf689SAlexander Kabaev this->_M_invalidate_if(_Not_equal(_M_base().end())); 285ffeaf689SAlexander Kabaev } 286ffeaf689SAlexander Kabaev }; 287ffeaf689SAlexander Kabaev 288ffeaf689SAlexander Kabaev template<typename _Key,typename _Tp,typename _Compare,typename _Allocator> 289ffeaf689SAlexander Kabaev inline bool 290ffeaf689SAlexander Kabaev operator==(const map<_Key,_Tp,_Compare,_Allocator>& __lhs, 291ffeaf689SAlexander Kabaev const map<_Key,_Tp,_Compare,_Allocator>& __rhs) 292ffeaf689SAlexander Kabaev { return __lhs._M_base() == __rhs._M_base(); } 293ffeaf689SAlexander Kabaev 294ffeaf689SAlexander Kabaev template<typename _Key,typename _Tp,typename _Compare,typename _Allocator> 295ffeaf689SAlexander Kabaev inline bool 296ffeaf689SAlexander Kabaev operator!=(const map<_Key,_Tp,_Compare,_Allocator>& __lhs, 297ffeaf689SAlexander Kabaev const map<_Key,_Tp,_Compare,_Allocator>& __rhs) 298ffeaf689SAlexander Kabaev { return __lhs._M_base() != __rhs._M_base(); } 299ffeaf689SAlexander Kabaev 300ffeaf689SAlexander Kabaev template<typename _Key,typename _Tp,typename _Compare,typename _Allocator> 301ffeaf689SAlexander Kabaev inline bool 302ffeaf689SAlexander Kabaev operator<(const map<_Key,_Tp,_Compare,_Allocator>& __lhs, 303ffeaf689SAlexander Kabaev const map<_Key,_Tp,_Compare,_Allocator>& __rhs) 304ffeaf689SAlexander Kabaev { return __lhs._M_base() < __rhs._M_base(); } 305ffeaf689SAlexander Kabaev 306ffeaf689SAlexander Kabaev template<typename _Key,typename _Tp,typename _Compare,typename _Allocator> 307ffeaf689SAlexander Kabaev inline bool 308ffeaf689SAlexander Kabaev operator<=(const map<_Key,_Tp,_Compare,_Allocator>& __lhs, 309ffeaf689SAlexander Kabaev const map<_Key,_Tp,_Compare,_Allocator>& __rhs) 310ffeaf689SAlexander Kabaev { return __lhs._M_base() <= __rhs._M_base(); } 311ffeaf689SAlexander Kabaev 312ffeaf689SAlexander Kabaev template<typename _Key,typename _Tp,typename _Compare,typename _Allocator> 313ffeaf689SAlexander Kabaev inline bool 314ffeaf689SAlexander Kabaev operator>=(const map<_Key,_Tp,_Compare,_Allocator>& __lhs, 315ffeaf689SAlexander Kabaev const map<_Key,_Tp,_Compare,_Allocator>& __rhs) 316ffeaf689SAlexander Kabaev { return __lhs._M_base() >= __rhs._M_base(); } 317ffeaf689SAlexander Kabaev 318ffeaf689SAlexander Kabaev template<typename _Key,typename _Tp,typename _Compare,typename _Allocator> 319ffeaf689SAlexander Kabaev inline bool 320ffeaf689SAlexander Kabaev operator>(const map<_Key,_Tp,_Compare,_Allocator>& __lhs, 321ffeaf689SAlexander Kabaev const map<_Key,_Tp,_Compare,_Allocator>& __rhs) 322ffeaf689SAlexander Kabaev { return __lhs._M_base() > __rhs._M_base(); } 323ffeaf689SAlexander Kabaev 324ffeaf689SAlexander Kabaev template<typename _Key,typename _Tp,typename _Compare,typename _Allocator> 325ffeaf689SAlexander Kabaev inline void swap(map<_Key,_Tp,_Compare,_Allocator> & __lhs,map<_Key,_Tp,_Compare,_Allocator> & __rhs)326ffeaf689SAlexander Kabaev swap(map<_Key,_Tp,_Compare,_Allocator>& __lhs, 327ffeaf689SAlexander Kabaev map<_Key,_Tp,_Compare,_Allocator>& __rhs) 328ffeaf689SAlexander Kabaev { __lhs.swap(__rhs); } 329*f8a1b7d9SAlexander Kabaev } // namespace __debug 330*f8a1b7d9SAlexander Kabaev } // namespace std 331ffeaf689SAlexander Kabaev 332ffeaf689SAlexander Kabaev #endif 333