ÿØÿà JFIF    ÿÛ „ ( %!1!%*+...983,7(-.- PKNd]8/cucharnu[// -*- C++ -*- forwarding header. // Copyright (C) 2015-2018 Free Software Foundation, Inc. // // This file is part of the GNU ISO C++ Library. This library is free // software; you can redistribute it and/or modify it under the // terms of the GNU General Public License as published by the // Free Software Foundation; either version 3, or (at your option) // any later version. // This library is distributed in the hope that it will be useful, // but WITHOUT ANY WARRANTY; without even the implied warranty of // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the // GNU General Public License for more details. // Under Section 7 of GPL version 3, you are granted additional // permissions described in the GCC Runtime Library Exception, version // 3.1, as published by the Free Software Foundation. // You should have received a copy of the GNU General Public License and // a copy of the GCC Runtime Library Exception along with this program; // see the files COPYING3 and COPYING.RUNTIME respectively. If not, see // . /** @file include/cuchar * This is a Standard C++ Library file. You should @c \#include this file * in your programs, rather than any of the @a *.h implementation files. * * This is the C++ version of the Standard C Library header @c uchar.h, * and its contents are (mostly) the same as that header, but are all * contained in the namespace @c std (except for names which are defined * as macros in C). */ // // ISO C++ 14882:2011 21.8 // #ifndef _GLIBCXX_CUCHAR #define _GLIBCXX_CUCHAR 1 #pragma GCC system_header #if __cplusplus < 201103L # include #else #include #include #if _GLIBCXX_USE_C11_UCHAR_CXX11 #include // Get rid of those macros defined in in lieu of real functions. #undef mbrtoc16 #undef c16rtomb #undef mbrtoc32 #undef c32rtomb namespace std _GLIBCXX_VISIBILITY(default) { _GLIBCXX_BEGIN_NAMESPACE_VERSION using ::mbrtoc16; using ::c16rtomb; using ::mbrtoc32; using ::c32rtomb; _GLIBCXX_END_NAMESPACE_VERSION } // namespace std #endif // _GLIBCXX_USE_C11_UCHAR_CXX11 #endif // C++11 #endif // _GLIBCXX_CUCHAR PKNd]iC 8/stdlib.hnu[// -*- C++ -*- compatibility header. // Copyright (C) 2002-2018 Free Software Foundation, Inc. // // This file is part of the GNU ISO C++ Library. This library is free // software; you can redistribute it and/or modify it under the // terms of the GNU General Public License as published by the // Free Software Foundation; either version 3, or (at your option) // any later version. // This library is distributed in the hope that it will be useful, // but WITHOUT ANY WARRANTY; without even the implied warranty of // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the // GNU General Public License for more details. // Under Section 7 of GPL version 3, you are granted additional // permissions described in the GCC Runtime Library Exception, version // 3.1, as published by the Free Software Foundation. // You should have received a copy of the GNU General Public License and // a copy of the GCC Runtime Library Exception along with this program; // see the files COPYING3 and COPYING.RUNTIME respectively. If not, see // . /** @file stdlib.h * This is a Standard C++ Library header. */ #if !defined __cplusplus || defined _GLIBCXX_INCLUDE_NEXT_C_HEADERS # include_next #else #ifndef _GLIBCXX_STDLIB_H #define _GLIBCXX_STDLIB_H 1 # include using std::abort; using std::atexit; using std::exit; #if __cplusplus >= 201103L # ifdef _GLIBCXX_HAVE_AT_QUICK_EXIT using std::at_quick_exit; # endif # ifdef _GLIBCXX_HAVE_QUICK_EXIT using std::quick_exit; # endif #endif #if _GLIBCXX_HOSTED using std::div_t; using std::ldiv_t; using std::abs; using std::atof; using std::atoi; using std::atol; using std::bsearch; using std::calloc; using std::div; using std::free; using std::getenv; using std::labs; using std::ldiv; using std::malloc; #ifdef _GLIBCXX_HAVE_MBSTATE_T using std::mblen; using std::mbstowcs; using std::mbtowc; #endif // _GLIBCXX_HAVE_MBSTATE_T using std::qsort; using std::rand; using std::realloc; using std::srand; using std::strtod; using std::strtol; using std::strtoul; using std::system; #ifdef _GLIBCXX_USE_WCHAR_T using std::wcstombs; using std::wctomb; #endif // _GLIBCXX_USE_WCHAR_T #endif #endif // _GLIBCXX_STDLIB_H #endif // __cplusplus PKNd]__ 8/ext/cast.hnu[// -*- C++ -*- // Copyright (C) 2008-2018 Free Software Foundation, Inc. // // This file is part of the GNU ISO C++ Library. This library is free // software; you can redistribute it and/or modify it under the // terms of the GNU General Public License as published by the // Free Software Foundation; either version 3, or (at your option) // any later version. // This library is distributed in the hope that it will be useful, // but WITHOUT ANY WARRANTY; without even the implied warranty of // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the // GNU General Public License for more details. // Under Section 7 of GPL version 3, you are granted additional // permissions described in the GCC Runtime Library Exception, version // 3.1, as published by the Free Software Foundation. // You should have received a copy of the GNU General Public License and // a copy of the GCC Runtime Library Exception along with this program; // see the files COPYING3 and COPYING.RUNTIME respectively. If not, see // . /** @file ext/cast.h * This is an internal header file, included by other library headers. * Do not attempt to use it directly. @headername{ext/pointer.h} */ #ifndef _GLIBCXX_CAST_H #define _GLIBCXX_CAST_H 1 namespace __gnu_cxx _GLIBCXX_VISIBILITY(default) { _GLIBCXX_BEGIN_NAMESPACE_VERSION /** * These functions are here to allow containers to support non standard * pointer types. For normal pointers, these resolve to the use of the * standard cast operation. For other types the functions will perform * the appropriate cast to/from the custom pointer class so long as that * class meets the following conditions: * 1) has a typedef element_type which names tehe type it points to. * 2) has a get() const method which returns element_type*. * 3) has a constructor which can take one element_type* argument. */ /** * This type supports the semantics of the pointer cast operators (below.) */ template struct _Caster { typedef typename _ToType::element_type* type; }; template struct _Caster<_ToType*> { typedef _ToType* type; }; /** * Casting operations for cases where _FromType is not a standard pointer. * _ToType can be a standard or non-standard pointer. Given that _FromType * is not a pointer, it must have a get() method that returns the standard * pointer equivalent of the address it points to, and must have an * element_type typedef which names the type it points to. */ template inline _ToType __static_pointer_cast(const _FromType& __arg) { return _ToType(static_cast:: type>(__arg.get())); } template inline _ToType __dynamic_pointer_cast(const _FromType& __arg) { return _ToType(dynamic_cast:: type>(__arg.get())); } template inline _ToType __const_pointer_cast(const _FromType& __arg) { return _ToType(const_cast:: type>(__arg.get())); } template inline _ToType __reinterpret_pointer_cast(const _FromType& __arg) { return _ToType(reinterpret_cast:: type>(__arg.get())); } /** * Casting operations for cases where _FromType is a standard pointer. * _ToType can be a standard or non-standard pointer. */ template inline _ToType __static_pointer_cast(_FromType* __arg) { return _ToType(static_cast:: type>(__arg)); } template inline _ToType __dynamic_pointer_cast(_FromType* __arg) { return _ToType(dynamic_cast:: type>(__arg)); } template inline _ToType __const_pointer_cast(_FromType* __arg) { return _ToType(const_cast:: type>(__arg)); } template inline _ToType __reinterpret_pointer_cast(_FromType* __arg) { return _ToType(reinterpret_cast:: type>(__arg)); } _GLIBCXX_END_NAMESPACE_VERSION } // namespace #endif // _GLIBCXX_CAST_H PKNd]$__8/ext/throw_allocator.hnu[// -*- C++ -*- // Copyright (C) 2005-2018 Free Software Foundation, Inc. // // This file is part of the GNU ISO C++ Library. This library is free // software; you can redistribute it and/or modify it under the terms // of the GNU General Public License as published by the Free Software // Foundation; either version 3, or (at your option) any later // version. // This library is distributed in the hope that it will be useful, but // WITHOUT ANY WARRANTY; without even the implied warranty of // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU // General Public License for more details. // Under Section 7 of GPL version 3, you are granted additional // permissions described in the GCC Runtime Library Exception, version // 3.1, as published by the Free Software Foundation. // You should have received a copy of the GNU General Public License and // a copy of the GCC Runtime Library Exception along with this program; // see the files COPYING3 and COPYING.RUNTIME respectively. If not, see // . // Copyright (C) 2004 Ami Tavory and Vladimir Dreizin, IBM-HRL. // Permission to use, copy, modify, sell, and distribute this software // is hereby granted without fee, provided that the above copyright // notice appears in all copies, and that both that copyright notice // and this permission notice appear in supporting documentation. None // of the above authors, nor IBM Haifa Research Laboratories, make any // representation about the suitability of this software for any // purpose. It is provided "as is" without express or implied // warranty. /** @file ext/throw_allocator.h * This file is a GNU extension to the Standard C++ Library. * * Contains two exception-generating types (throw_value, throw_allocator) * intended to be used as value and allocator types while testing * exception safety in templatized containers and algorithms. The * allocator has additional log and debug features. The exception * generated is of type forced_exception_error. */ #ifndef _THROW_ALLOCATOR_H #define _THROW_ALLOCATOR_H 1 #include #include #include #include #include #include #include #include #include #if __cplusplus >= 201103L # include # include #else # include # include #endif namespace __gnu_cxx _GLIBCXX_VISIBILITY(default) { _GLIBCXX_BEGIN_NAMESPACE_VERSION /** * @brief Thown by exception safety machinery. * @ingroup exceptions */ struct forced_error : public std::exception { }; // Substitute for forced_error object when -fno-exceptions. inline void __throw_forced_error() { _GLIBCXX_THROW_OR_ABORT(forced_error()); } /** * @brief Base class for checking address and label information * about allocations. Create a std::map between the allocated * address (void*) and a datum for annotations, which are a pair of * numbers corresponding to label and allocated size. */ struct annotate_base { annotate_base() { label(); map_alloc(); } static void set_label(size_t l) { label() = l; } static size_t get_label() { return label(); } void insert(void* p, size_t size) { if (!p) { std::string error("annotate_base::insert null insert!\n"); log_to_string(error, make_entry(p, size)); std::__throw_logic_error(error.c_str()); } const_iterator found = map_alloc().find(p); if (found != map_alloc().end()) { std::string error("annotate_base::insert double insert!\n"); log_to_string(error, make_entry(p, size)); log_to_string(error, *found); std::__throw_logic_error(error.c_str()); } map_alloc().insert(make_entry(p, size)); } void erase(void* p, size_t size) { check_allocated(p, size); map_alloc().erase(p); } #if __cplusplus >= 201103L void insert_construct(void* p) { if (!p) { std::string error("annotate_base::insert_construct null!\n"); std::__throw_logic_error(error.c_str()); } auto found = map_construct().find(p); if (found != map_construct().end()) { std::string error("annotate_base::insert_construct double insert!\n"); log_to_string(error, std::make_pair(p, get_label())); log_to_string(error, *found); std::__throw_logic_error(error.c_str()); } map_construct().insert(std::make_pair(p, get_label())); } void erase_construct(void* p) { check_constructed(p); map_construct().erase(p); } #endif // See if a particular address and allocation size has been saved. inline void check_allocated(void* p, size_t size) { const_iterator found = map_alloc().find(p); if (found == map_alloc().end()) { std::string error("annotate_base::check_allocated by value " "null erase!\n"); log_to_string(error, make_entry(p, size)); std::__throw_logic_error(error.c_str()); } if (found->second.second != size) { std::string error("annotate_base::check_allocated by value " "wrong-size erase!\n"); log_to_string(error, make_entry(p, size)); log_to_string(error, *found); std::__throw_logic_error(error.c_str()); } } // See if a given label has been allocated. inline void check(size_t label) { std::string found; { const_iterator beg = map_alloc().begin(); const_iterator end = map_alloc().end(); while (beg != end) { if (beg->second.first == label) log_to_string(found, *beg); ++beg; } } #if __cplusplus >= 201103L { auto beg = map_construct().begin(); auto end = map_construct().end(); while (beg != end) { if (beg->second == label) log_to_string(found, *beg); ++beg; } } #endif if (!found.empty()) { std::string error("annotate_base::check by label\n"); error += found; std::__throw_logic_error(error.c_str()); } } // See if there is anything left allocated or constructed. inline static void check() { std::string found; { const_iterator beg = map_alloc().begin(); const_iterator end = map_alloc().end(); while (beg != end) { log_to_string(found, *beg); ++beg; } } #if __cplusplus >= 201103L { auto beg = map_construct().begin(); auto end = map_construct().end(); while (beg != end) { log_to_string(found, *beg); ++beg; } } #endif if (!found.empty()) { std::string error("annotate_base::check \n"); error += found; std::__throw_logic_error(error.c_str()); } } #if __cplusplus >= 201103L inline void check_constructed(void* p) { auto found = map_construct().find(p); if (found == map_construct().end()) { std::string error("annotate_base::check_constructed not " "constructed!\n"); log_to_string(error, std::make_pair(p, get_label())); std::__throw_logic_error(error.c_str()); } } inline void check_constructed(size_t label) { auto beg = map_construct().begin(); auto end = map_construct().end(); std::string found; while (beg != end) { if (beg->second == label) log_to_string(found, *beg); ++beg; } if (!found.empty()) { std::string error("annotate_base::check_constructed by label\n"); error += found; std::__throw_logic_error(error.c_str()); } } #endif private: typedef std::pair data_type; typedef std::map map_alloc_type; typedef map_alloc_type::value_type entry_type; typedef map_alloc_type::const_iterator const_iterator; typedef map_alloc_type::const_reference const_reference; #if __cplusplus >= 201103L typedef std::map map_construct_type; #endif friend std::ostream& operator<<(std::ostream&, const annotate_base&); entry_type make_entry(void* p, size_t size) { return std::make_pair(p, data_type(get_label(), size)); } static void log_to_string(std::string& s, const_reference ref) { char buf[40]; const char tab('\t'); s += "label: "; unsigned long l = static_cast(ref.second.first); __builtin_sprintf(buf, "%lu", l); s += buf; s += tab; s += "size: "; l = static_cast(ref.second.second); __builtin_sprintf(buf, "%lu", l); s += buf; s += tab; s += "address: "; __builtin_sprintf(buf, "%p", ref.first); s += buf; s += '\n'; } #if __cplusplus >= 201103L static void log_to_string(std::string& s, const std::pair& ref) { char buf[40]; const char tab('\t'); s += "label: "; unsigned long l = static_cast(ref.second); __builtin_sprintf(buf, "%lu", l); s += buf; s += tab; s += "address: "; __builtin_sprintf(buf, "%p", ref.first); s += buf; s += '\n'; } #endif static size_t& label() { static size_t _S_label(std::numeric_limits::max()); return _S_label; } static map_alloc_type& map_alloc() { static map_alloc_type _S_map; return _S_map; } #if __cplusplus >= 201103L static map_construct_type& map_construct() { static map_construct_type _S_map; return _S_map; } #endif }; inline std::ostream& operator<<(std::ostream& os, const annotate_base& __b) { std::string error; typedef annotate_base base_type; { base_type::const_iterator beg = __b.map_alloc().begin(); base_type::const_iterator end = __b.map_alloc().end(); for (; beg != end; ++beg) __b.log_to_string(error, *beg); } #if __cplusplus >= 201103L { auto beg = __b.map_construct().begin(); auto end = __b.map_construct().end(); for (; beg != end; ++beg) __b.log_to_string(error, *beg); } #endif return os << error; } /** * @brief Base struct for condition policy. * * Requires a public member function with the signature * void throw_conditionally() */ struct condition_base { virtual ~condition_base() { }; }; /** * @brief Base class for incremental control and throw. */ struct limit_condition : public condition_base { // Scope-level adjustor objects: set limit for throw at the // beginning of a scope block, and restores to previous limit when // object is destroyed on exiting the block. struct adjustor_base { private: const size_t _M_orig; public: adjustor_base() : _M_orig(limit()) { } virtual ~adjustor_base() { set_limit(_M_orig); } }; /// Never enter the condition. struct never_adjustor : public adjustor_base { never_adjustor() { set_limit(std::numeric_limits::max()); } }; /// Always enter the condition. struct always_adjustor : public adjustor_base { always_adjustor() { set_limit(count()); } }; /// Enter the nth condition. struct limit_adjustor : public adjustor_base { limit_adjustor(const size_t __l) { set_limit(__l); } }; // Increment _S_count every time called. // If _S_count matches the limit count, throw. static void throw_conditionally() { if (count() == limit()) __throw_forced_error(); ++count(); } static size_t& count() { static size_t _S_count(0); return _S_count; } static size_t& limit() { static size_t _S_limit(std::numeric_limits::max()); return _S_limit; } // Zero the throw counter, set limit to argument. static void set_limit(const size_t __l) { limit() = __l; count() = 0; } }; /** * @brief Base class for random probability control and throw. */ struct random_condition : public condition_base { // Scope-level adjustor objects: set probability for throw at the // beginning of a scope block, and restores to previous // probability when object is destroyed on exiting the block. struct adjustor_base { private: const double _M_orig; public: adjustor_base() : _M_orig(probability()) { } virtual ~adjustor_base() { set_probability(_M_orig); } }; /// Group condition. struct group_adjustor : public adjustor_base { group_adjustor(size_t size) { set_probability(1 - std::pow(double(1 - probability()), double(0.5 / (size + 1)))); } }; /// Never enter the condition. struct never_adjustor : public adjustor_base { never_adjustor() { set_probability(0); } }; /// Always enter the condition. struct always_adjustor : public adjustor_base { always_adjustor() { set_probability(1); } }; random_condition() { probability(); engine(); } static void set_probability(double __p) { probability() = __p; } static void throw_conditionally() { if (generate() < probability()) __throw_forced_error(); } void seed(unsigned long __s) { engine().seed(__s); } private: #if __cplusplus >= 201103L typedef std::uniform_real_distribution distribution_type; typedef std::mt19937 engine_type; #else typedef std::tr1::uniform_real distribution_type; typedef std::tr1::mt19937 engine_type; #endif static double generate() { #if __cplusplus >= 201103L const distribution_type distribution(0, 1); static auto generator = std::bind(distribution, engine()); #else // Use variate_generator to get normalized results. typedef std::tr1::variate_generator gen_t; distribution_type distribution(0, 1); static gen_t generator(engine(), distribution); #endif double random = generator(); if (random < distribution.min() || random > distribution.max()) { std::string __s("random_condition::generate"); __s += "\n"; __s += "random number generated is: "; char buf[40]; __builtin_sprintf(buf, "%f", random); __s += buf; std::__throw_out_of_range(__s.c_str()); } return random; } static double& probability() { static double _S_p; return _S_p; } static engine_type& engine() { static engine_type _S_e; return _S_e; } }; /** * @brief Class with exception generation control. Intended to be * used as a value_type in templatized code. * * Note: Destructor not allowed to throw. */ template struct throw_value_base : public _Cond { typedef _Cond condition_type; using condition_type::throw_conditionally; std::size_t _M_i; #ifndef _GLIBCXX_IS_AGGREGATE throw_value_base() : _M_i(0) { throw_conditionally(); } throw_value_base(const throw_value_base& __v) : _M_i(__v._M_i) { throw_conditionally(); } #if __cplusplus >= 201103L // Shall not throw. throw_value_base(throw_value_base&&) = default; #endif explicit throw_value_base(const std::size_t __i) : _M_i(__i) { throw_conditionally(); } #endif throw_value_base& operator=(const throw_value_base& __v) { throw_conditionally(); _M_i = __v._M_i; return *this; } #if __cplusplus >= 201103L // Shall not throw. throw_value_base& operator=(throw_value_base&&) = default; #endif throw_value_base& operator++() { throw_conditionally(); ++_M_i; return *this; } }; template inline void swap(throw_value_base<_Cond>& __a, throw_value_base<_Cond>& __b) { typedef throw_value_base<_Cond> throw_value; throw_value::throw_conditionally(); throw_value orig(__a); __a = __b; __b = orig; } // General instantiable types requirements. template inline bool operator==(const throw_value_base<_Cond>& __a, const throw_value_base<_Cond>& __b) { typedef throw_value_base<_Cond> throw_value; throw_value::throw_conditionally(); bool __ret = __a._M_i == __b._M_i; return __ret; } template inline bool operator<(const throw_value_base<_Cond>& __a, const throw_value_base<_Cond>& __b) { typedef throw_value_base<_Cond> throw_value; throw_value::throw_conditionally(); bool __ret = __a._M_i < __b._M_i; return __ret; } // Numeric algorithms instantiable types requirements. template inline throw_value_base<_Cond> operator+(const throw_value_base<_Cond>& __a, const throw_value_base<_Cond>& __b) { typedef throw_value_base<_Cond> throw_value; throw_value::throw_conditionally(); throw_value __ret(__a._M_i + __b._M_i); return __ret; } template inline throw_value_base<_Cond> operator-(const throw_value_base<_Cond>& __a, const throw_value_base<_Cond>& __b) { typedef throw_value_base<_Cond> throw_value; throw_value::throw_conditionally(); throw_value __ret(__a._M_i - __b._M_i); return __ret; } template inline throw_value_base<_Cond> operator*(const throw_value_base<_Cond>& __a, const throw_value_base<_Cond>& __b) { typedef throw_value_base<_Cond> throw_value; throw_value::throw_conditionally(); throw_value __ret(__a._M_i * __b._M_i); return __ret; } /// Type throwing via limit condition. struct throw_value_limit : public throw_value_base { typedef throw_value_base base_type; #ifndef _GLIBCXX_IS_AGGREGATE throw_value_limit() { } throw_value_limit(const throw_value_limit& __other) : base_type(__other._M_i) { } #if __cplusplus >= 201103L throw_value_limit(throw_value_limit&&) = default; #endif explicit throw_value_limit(const std::size_t __i) : base_type(__i) { } #endif throw_value_limit& operator=(const throw_value_limit& __other) { base_type::operator=(__other); return *this; } #if __cplusplus >= 201103L throw_value_limit& operator=(throw_value_limit&&) = default; #endif }; /// Type throwing via random condition. struct throw_value_random : public throw_value_base { typedef throw_value_base base_type; #ifndef _GLIBCXX_IS_AGGREGATE throw_value_random() { } throw_value_random(const throw_value_random& __other) : base_type(__other._M_i) { } #if __cplusplus >= 201103L throw_value_random(throw_value_random&&) = default; #endif explicit throw_value_random(const std::size_t __i) : base_type(__i) { } #endif throw_value_random& operator=(const throw_value_random& __other) { base_type::operator=(__other); return *this; } #if __cplusplus >= 201103L throw_value_random& operator=(throw_value_random&&) = default; #endif }; /** * @brief Allocator class with logging and exception generation control. * Intended to be used as an allocator_type in templatized code. * @ingroup allocators * * Note: Deallocate not allowed to throw. */ template class throw_allocator_base : public annotate_base, public _Cond { public: typedef size_t size_type; typedef ptrdiff_t difference_type; typedef _Tp value_type; typedef value_type* pointer; typedef const value_type* const_pointer; typedef value_type& reference; typedef const value_type& const_reference; #if __cplusplus >= 201103L // _GLIBCXX_RESOLVE_LIB_DEFECTS // 2103. std::allocator propagate_on_container_move_assignment typedef std::true_type propagate_on_container_move_assignment; #endif private: typedef _Cond condition_type; std::allocator _M_allocator; using condition_type::throw_conditionally; public: size_type max_size() const _GLIBCXX_USE_NOEXCEPT { return _M_allocator.max_size(); } pointer address(reference __x) const _GLIBCXX_NOEXCEPT { return std::__addressof(__x); } const_pointer address(const_reference __x) const _GLIBCXX_NOEXCEPT { return std::__addressof(__x); } pointer allocate(size_type __n, std::allocator::const_pointer hint = 0) { if (__n > this->max_size()) std::__throw_bad_alloc(); throw_conditionally(); pointer const a = _M_allocator.allocate(__n, hint); insert(a, sizeof(value_type) * __n); return a; } #if __cplusplus >= 201103L template void construct(_Up* __p, _Args&&... __args) { _M_allocator.construct(__p, std::forward<_Args>(__args)...); insert_construct(__p); } template void destroy(_Up* __p) { erase_construct(__p); _M_allocator.destroy(__p); } #else void construct(pointer __p, const value_type& val) { return _M_allocator.construct(__p, val); } void destroy(pointer __p) { _M_allocator.destroy(__p); } #endif void deallocate(pointer __p, size_type __n) { erase(__p, sizeof(value_type) * __n); _M_allocator.deallocate(__p, __n); } void check_allocated(pointer __p, size_type __n) { size_type __t = sizeof(value_type) * __n; annotate_base::check_allocated(__p, __t); } void check(size_type __n) { annotate_base::check(__n); } }; template inline bool operator==(const throw_allocator_base<_Tp, _Cond>&, const throw_allocator_base<_Tp, _Cond>&) { return true; } template inline bool operator!=(const throw_allocator_base<_Tp, _Cond>&, const throw_allocator_base<_Tp, _Cond>&) { return false; } /// Allocator throwing via limit condition. template struct throw_allocator_limit : public throw_allocator_base<_Tp, limit_condition> { template struct rebind { typedef throw_allocator_limit<_Tp1> other; }; throw_allocator_limit() _GLIBCXX_USE_NOEXCEPT { } throw_allocator_limit(const throw_allocator_limit&) _GLIBCXX_USE_NOEXCEPT { } template throw_allocator_limit(const throw_allocator_limit<_Tp1>&) _GLIBCXX_USE_NOEXCEPT { } ~throw_allocator_limit() _GLIBCXX_USE_NOEXCEPT { } }; /// Allocator throwing via random condition. template struct throw_allocator_random : public throw_allocator_base<_Tp, random_condition> { template struct rebind { typedef throw_allocator_random<_Tp1> other; }; throw_allocator_random() _GLIBCXX_USE_NOEXCEPT { } throw_allocator_random(const throw_allocator_random&) _GLIBCXX_USE_NOEXCEPT { } template throw_allocator_random(const throw_allocator_random<_Tp1>&) _GLIBCXX_USE_NOEXCEPT { } ~throw_allocator_random() _GLIBCXX_USE_NOEXCEPT { } }; _GLIBCXX_END_NAMESPACE_VERSION } // namespace #if __cplusplus >= 201103L # include namespace std _GLIBCXX_VISIBILITY(default) { /// Explicit specialization of std::hash for __gnu_cxx::throw_value_limit. template<> struct hash<__gnu_cxx::throw_value_limit> : public std::unary_function<__gnu_cxx::throw_value_limit, size_t> { size_t operator()(const __gnu_cxx::throw_value_limit& __val) const { __gnu_cxx::throw_value_limit::throw_conditionally(); std::hash __h; size_t __result = __h(__val._M_i); return __result; } }; /// Explicit specialization of std::hash for __gnu_cxx::throw_value_random. template<> struct hash<__gnu_cxx::throw_value_random> : public std::unary_function<__gnu_cxx::throw_value_random, size_t> { size_t operator()(const __gnu_cxx::throw_value_random& __val) const { __gnu_cxx::throw_value_random::throw_conditionally(); std::hash __h; size_t __result = __h(__val._M_i); return __result; } }; } // end namespace std #endif #endif PKNd],y1778/ext/functionalnu[// Functional extensions -*- C++ -*- // Copyright (C) 2002-2018 Free Software Foundation, Inc. // // This file is part of the GNU ISO C++ Library. This library is free // software; you can redistribute it and/or modify it under the // terms of the GNU General Public License as published by the // Free Software Foundation; either version 3, or (at your option) // any later version. // This library is distributed in the hope that it will be useful, // but WITHOUT ANY WARRANTY; without even the implied warranty of // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the // GNU General Public License for more details. // Under Section 7 of GPL version 3, you are granted additional // permissions described in the GCC Runtime Library Exception, version // 3.1, as published by the Free Software Foundation. // You should have received a copy of the GNU General Public License and // a copy of the GCC Runtime Library Exception along with this program; // see the files COPYING3 and COPYING.RUNTIME respectively. If not, see // . /* * * Copyright (c) 1994 * Hewlett-Packard Company * * Permission to use, copy, modify, distribute and sell this software * and its documentation for any purpose is hereby granted without fee, * provided that the above copyright notice appear in all copies and * that both that copyright notice and this permission notice appear * in supporting documentation. Hewlett-Packard Company makes no * representations about the suitability of this software for any * purpose. It is provided "as is" without express or implied warranty. * * * Copyright (c) 1996 * Silicon Graphics Computer Systems, Inc. * * Permission to use, copy, modify, distribute and sell this software * and its documentation for any purpose is hereby granted without fee, * provided that the above copyright notice appear in all copies and * that both that copyright notice and this permission notice appear * in supporting documentation. Silicon Graphics makes no * representations about the suitability of this software for any * purpose. It is provided "as is" without express or implied warranty. */ /** @file ext/functional * This file is a GNU extension to the Standard C++ Library (possibly * containing extensions from the HP/SGI STL subset). */ #ifndef _EXT_FUNCTIONAL #define _EXT_FUNCTIONAL 1 #pragma GCC system_header #include namespace __gnu_cxx _GLIBCXX_VISIBILITY(default) { _GLIBCXX_BEGIN_NAMESPACE_VERSION using std::size_t; using std::unary_function; using std::binary_function; using std::mem_fun1_t; using std::const_mem_fun1_t; using std::mem_fun1_ref_t; using std::const_mem_fun1_ref_t; /** The @c identity_element functions are not part of the C++ * standard; SGI provided them as an extension. Its argument is an * operation, and its return value is the identity element for that * operation. It is overloaded for addition and multiplication, * and you can overload it for your own nefarious operations. * * @addtogroup SGIextensions * @{ */ /// An \link SGIextensions SGI extension \endlink. template inline _Tp identity_element(std::plus<_Tp>) { return _Tp(0); } /// An \link SGIextensions SGI extension \endlink. template inline _Tp identity_element(std::multiplies<_Tp>) { return _Tp(1); } /** @} */ /** As an extension to the binders, SGI provided composition functors and * wrapper functions to aid in their creation. The @c unary_compose * functor is constructed from two functions/functors, @c f and @c g. * Calling @c operator() with a single argument @c x returns @c f(g(x)). * The function @c compose1 takes the two functions and constructs a * @c unary_compose variable for you. * * @c binary_compose is constructed from three functors, @c f, @c g1, * and @c g2. Its @c operator() returns @c f(g1(x),g2(x)). The function * compose2 takes f, g1, and g2, and constructs the @c binary_compose * instance for you. For example, if @c f returns an int, then * \code * int answer = (compose2(f,g1,g2))(x); * \endcode * is equivalent to * \code * int temp1 = g1(x); * int temp2 = g2(x); * int answer = f(temp1,temp2); * \endcode * But the first form is more compact, and can be passed around as a * functor to other algorithms. * * @addtogroup SGIextensions * @{ */ /// An \link SGIextensions SGI extension \endlink. template class unary_compose : public unary_function { protected: _Operation1 _M_fn1; _Operation2 _M_fn2; public: unary_compose(const _Operation1& __x, const _Operation2& __y) : _M_fn1(__x), _M_fn2(__y) {} typename _Operation1::result_type operator()(const typename _Operation2::argument_type& __x) const { return _M_fn1(_M_fn2(__x)); } }; /// An \link SGIextensions SGI extension \endlink. template inline unary_compose<_Operation1, _Operation2> compose1(const _Operation1& __fn1, const _Operation2& __fn2) { return unary_compose<_Operation1,_Operation2>(__fn1, __fn2); } /// An \link SGIextensions SGI extension \endlink. template class binary_compose : public unary_function { protected: _Operation1 _M_fn1; _Operation2 _M_fn2; _Operation3 _M_fn3; public: binary_compose(const _Operation1& __x, const _Operation2& __y, const _Operation3& __z) : _M_fn1(__x), _M_fn2(__y), _M_fn3(__z) { } typename _Operation1::result_type operator()(const typename _Operation2::argument_type& __x) const { return _M_fn1(_M_fn2(__x), _M_fn3(__x)); } }; /// An \link SGIextensions SGI extension \endlink. template inline binary_compose<_Operation1, _Operation2, _Operation3> compose2(const _Operation1& __fn1, const _Operation2& __fn2, const _Operation3& __fn3) { return binary_compose<_Operation1, _Operation2, _Operation3> (__fn1, __fn2, __fn3); } /** @} */ /** As an extension, SGI provided a functor called @c identity. When a * functor is required but no operations are desired, this can be used as a * pass-through. Its @c operator() returns its argument unchanged. * * @addtogroup SGIextensions */ template struct identity : public std::_Identity<_Tp> {}; /** @c select1st and @c select2nd are extensions provided by SGI. Their * @c operator()s * take a @c std::pair as an argument, and return either the first member * or the second member, respectively. They can be used (especially with * the composition functors) to @a strip data from a sequence before * performing the remainder of an algorithm. * * @addtogroup SGIextensions * @{ */ /// An \link SGIextensions SGI extension \endlink. template struct select1st : public std::_Select1st<_Pair> {}; /// An \link SGIextensions SGI extension \endlink. template struct select2nd : public std::_Select2nd<_Pair> {}; /** @} */ // extension documented next template struct _Project1st : public binary_function<_Arg1, _Arg2, _Arg1> { _Arg1 operator()(const _Arg1& __x, const _Arg2&) const { return __x; } }; template struct _Project2nd : public binary_function<_Arg1, _Arg2, _Arg2> { _Arg2 operator()(const _Arg1&, const _Arg2& __y) const { return __y; } }; /** The @c operator() of the @c project1st functor takes two arbitrary * arguments and returns the first one, while @c project2nd returns the * second one. They are extensions provided by SGI. * * @addtogroup SGIextensions * @{ */ /// An \link SGIextensions SGI extension \endlink. template struct project1st : public _Project1st<_Arg1, _Arg2> {}; /// An \link SGIextensions SGI extension \endlink. template struct project2nd : public _Project2nd<_Arg1, _Arg2> {}; /** @} */ // extension documented next template struct _Constant_void_fun { typedef _Result result_type; result_type _M_val; _Constant_void_fun(const result_type& __v) : _M_val(__v) {} const result_type& operator()() const { return _M_val; } }; template struct _Constant_unary_fun { typedef _Argument argument_type; typedef _Result result_type; result_type _M_val; _Constant_unary_fun(const result_type& __v) : _M_val(__v) {} const result_type& operator()(const _Argument&) const { return _M_val; } }; template struct _Constant_binary_fun { typedef _Arg1 first_argument_type; typedef _Arg2 second_argument_type; typedef _Result result_type; _Result _M_val; _Constant_binary_fun(const _Result& __v) : _M_val(__v) {} const result_type& operator()(const _Arg1&, const _Arg2&) const { return _M_val; } }; /** These three functors are each constructed from a single arbitrary * variable/value. Later, their @c operator()s completely ignore any * arguments passed, and return the stored value. * - @c constant_void_fun's @c operator() takes no arguments * - @c constant_unary_fun's @c operator() takes one argument (ignored) * - @c constant_binary_fun's @c operator() takes two arguments (ignored) * * The helper creator functions @c constant0, @c constant1, and * @c constant2 each take a @a result argument and construct variables of * the appropriate functor type. * * @addtogroup SGIextensions * @{ */ /// An \link SGIextensions SGI extension \endlink. template struct constant_void_fun : public _Constant_void_fun<_Result> { constant_void_fun(const _Result& __v) : _Constant_void_fun<_Result>(__v) {} }; /// An \link SGIextensions SGI extension \endlink. template struct constant_unary_fun : public _Constant_unary_fun<_Result, _Argument> { constant_unary_fun(const _Result& __v) : _Constant_unary_fun<_Result, _Argument>(__v) {} }; /// An \link SGIextensions SGI extension \endlink. template struct constant_binary_fun : public _Constant_binary_fun<_Result, _Arg1, _Arg2> { constant_binary_fun(const _Result& __v) : _Constant_binary_fun<_Result, _Arg1, _Arg2>(__v) {} }; /// An \link SGIextensions SGI extension \endlink. template inline constant_void_fun<_Result> constant0(const _Result& __val) { return constant_void_fun<_Result>(__val); } /// An \link SGIextensions SGI extension \endlink. template inline constant_unary_fun<_Result, _Result> constant1(const _Result& __val) { return constant_unary_fun<_Result, _Result>(__val); } /// An \link SGIextensions SGI extension \endlink. template inline constant_binary_fun<_Result,_Result,_Result> constant2(const _Result& __val) { return constant_binary_fun<_Result, _Result, _Result>(__val); } /** @} */ /** The @c subtractive_rng class is documented on * SGI's site. * Note that this code assumes that @c int is 32 bits. * * @ingroup SGIextensions */ class subtractive_rng : public unary_function { private: unsigned int _M_table[55]; size_t _M_index1; size_t _M_index2; public: /// Returns a number less than the argument. unsigned int operator()(unsigned int __limit) { _M_index1 = (_M_index1 + 1) % 55; _M_index2 = (_M_index2 + 1) % 55; _M_table[_M_index1] = _M_table[_M_index1] - _M_table[_M_index2]; return _M_table[_M_index1] % __limit; } void _M_initialize(unsigned int __seed) { unsigned int __k = 1; _M_table[54] = __seed; size_t __i; for (__i = 0; __i < 54; __i++) { size_t __ii = (21 * (__i + 1) % 55) - 1; _M_table[__ii] = __k; __k = __seed - __k; __seed = _M_table[__ii]; } for (int __loop = 0; __loop < 4; __loop++) { for (__i = 0; __i < 55; __i++) _M_table[__i] = _M_table[__i] - _M_table[(1 + __i + 30) % 55]; } _M_index1 = 0; _M_index2 = 31; } /// Ctor allowing you to initialize the seed. subtractive_rng(unsigned int __seed) { _M_initialize(__seed); } /// Default ctor; initializes its state with some number you don't see. subtractive_rng() { _M_initialize(161803398u); } }; // Mem_fun adaptor helper functions mem_fun1 and mem_fun1_ref, // provided for backward compatibility, they are no longer part of // the C++ standard. template inline mem_fun1_t<_Ret, _Tp, _Arg> mem_fun1(_Ret (_Tp::*__f)(_Arg)) { return mem_fun1_t<_Ret, _Tp, _Arg>(__f); } template inline const_mem_fun1_t<_Ret, _Tp, _Arg> mem_fun1(_Ret (_Tp::*__f)(_Arg) const) { return const_mem_fun1_t<_Ret, _Tp, _Arg>(__f); } template inline mem_fun1_ref_t<_Ret, _Tp, _Arg> mem_fun1_ref(_Ret (_Tp::*__f)(_Arg)) { return mem_fun1_ref_t<_Ret, _Tp, _Arg>(__f); } template inline const_mem_fun1_ref_t<_Ret, _Tp, _Arg> mem_fun1_ref(_Ret (_Tp::*__f)(_Arg) const) { return const_mem_fun1_ref_t<_Ret, _Tp, _Arg>(__f); } _GLIBCXX_END_NAMESPACE_VERSION } // namespace #endif PKNd]6oN|N|8/ext/bitmap_allocator.hnu[// Bitmap Allocator. -*- C++ -*- // Copyright (C) 2004-2018 Free Software Foundation, Inc. // // This file is part of the GNU ISO C++ Library. This library is free // software; you can redistribute it and/or modify it under the // terms of the GNU General Public License as published by the // Free Software Foundation; either version 3, or (at your option) // any later version. // This library is distributed in the hope that it will be useful, // but WITHOUT ANY WARRANTY; without even the implied warranty of // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the // GNU General Public License for more details. // Under Section 7 of GPL version 3, you are granted additional // permissions described in the GCC Runtime Library Exception, version // 3.1, as published by the Free Software Foundation. // You should have received a copy of the GNU General Public License and // a copy of the GCC Runtime Library Exception along with this program; // see the files COPYING3 and COPYING.RUNTIME respectively. If not, see // . /** @file ext/bitmap_allocator.h * This file is a GNU extension to the Standard C++ Library. */ #ifndef _BITMAP_ALLOCATOR_H #define _BITMAP_ALLOCATOR_H 1 #include // For std::pair. #include // For __throw_bad_alloc(). #include // For greater_equal, and less_equal. #include // For operator new. #include // _GLIBCXX_DEBUG_ASSERT #include #include /** @brief The constant in the expression below is the alignment * required in bytes. */ #define _BALLOC_ALIGN_BYTES 8 namespace __gnu_cxx _GLIBCXX_VISIBILITY(default) { _GLIBCXX_BEGIN_NAMESPACE_VERSION using std::size_t; using std::ptrdiff_t; namespace __detail { /** @class __mini_vector bitmap_allocator.h bitmap_allocator.h * * @brief __mini_vector<> is a stripped down version of the * full-fledged std::vector<>. * * It is to be used only for built-in types or PODs. Notable * differences are: * * 1. Not all accessor functions are present. * 2. Used ONLY for PODs. * 3. No Allocator template argument. Uses ::operator new() to get * memory, and ::operator delete() to free it. * Caveat: The dtor does NOT free the memory allocated, so this a * memory-leaking vector! */ template class __mini_vector { __mini_vector(const __mini_vector&); __mini_vector& operator=(const __mini_vector&); public: typedef _Tp value_type; typedef _Tp* pointer; typedef _Tp& reference; typedef const _Tp& const_reference; typedef size_t size_type; typedef ptrdiff_t difference_type; typedef pointer iterator; private: pointer _M_start; pointer _M_finish; pointer _M_end_of_storage; size_type _M_space_left() const throw() { return _M_end_of_storage - _M_finish; } pointer allocate(size_type __n) { return static_cast(::operator new(__n * sizeof(_Tp))); } void deallocate(pointer __p, size_type) { ::operator delete(__p); } public: // Members used: size(), push_back(), pop_back(), // insert(iterator, const_reference), erase(iterator), // begin(), end(), back(), operator[]. __mini_vector() : _M_start(0), _M_finish(0), _M_end_of_storage(0) { } size_type size() const throw() { return _M_finish - _M_start; } iterator begin() const throw() { return this->_M_start; } iterator end() const throw() { return this->_M_finish; } reference back() const throw() { return *(this->end() - 1); } reference operator[](const size_type __pos) const throw() { return this->_M_start[__pos]; } void insert(iterator __pos, const_reference __x); void push_back(const_reference __x) { if (this->_M_space_left()) { *this->end() = __x; ++this->_M_finish; } else this->insert(this->end(), __x); } void pop_back() throw() { --this->_M_finish; } void erase(iterator __pos) throw(); void clear() throw() { this->_M_finish = this->_M_start; } }; // Out of line function definitions. template void __mini_vector<_Tp>:: insert(iterator __pos, const_reference __x) { if (this->_M_space_left()) { size_type __to_move = this->_M_finish - __pos; iterator __dest = this->end(); iterator __src = this->end() - 1; ++this->_M_finish; while (__to_move) { *__dest = *__src; --__dest; --__src; --__to_move; } *__pos = __x; } else { size_type __new_size = this->size() ? this->size() * 2 : 1; iterator __new_start = this->allocate(__new_size); iterator __first = this->begin(); iterator __start = __new_start; while (__first != __pos) { *__start = *__first; ++__start; ++__first; } *__start = __x; ++__start; while (__first != this->end()) { *__start = *__first; ++__start; ++__first; } if (this->_M_start) this->deallocate(this->_M_start, this->size()); this->_M_start = __new_start; this->_M_finish = __start; this->_M_end_of_storage = this->_M_start + __new_size; } } template void __mini_vector<_Tp>:: erase(iterator __pos) throw() { while (__pos + 1 != this->end()) { *__pos = __pos[1]; ++__pos; } --this->_M_finish; } template struct __mv_iter_traits { typedef typename _Tp::value_type value_type; typedef typename _Tp::difference_type difference_type; }; template struct __mv_iter_traits<_Tp*> { typedef _Tp value_type; typedef ptrdiff_t difference_type; }; enum { bits_per_byte = 8, bits_per_block = sizeof(size_t) * size_t(bits_per_byte) }; template _ForwardIterator __lower_bound(_ForwardIterator __first, _ForwardIterator __last, const _Tp& __val, _Compare __comp) { typedef typename __mv_iter_traits<_ForwardIterator>::difference_type _DistanceType; _DistanceType __len = __last - __first; _DistanceType __half; _ForwardIterator __middle; while (__len > 0) { __half = __len >> 1; __middle = __first; __middle += __half; if (__comp(*__middle, __val)) { __first = __middle; ++__first; __len = __len - __half - 1; } else __len = __half; } return __first; } /** @brief The number of Blocks pointed to by the address pair * passed to the function. */ template inline size_t __num_blocks(_AddrPair __ap) { return (__ap.second - __ap.first) + 1; } /** @brief The number of Bit-maps pointed to by the address pair * passed to the function. */ template inline size_t __num_bitmaps(_AddrPair __ap) { return __num_blocks(__ap) / size_t(bits_per_block); } // _Tp should be a pointer type. template class _Inclusive_between : public std::unary_function, bool> { typedef _Tp pointer; pointer _M_ptr_value; typedef typename std::pair<_Tp, _Tp> _Block_pair; public: _Inclusive_between(pointer __ptr) : _M_ptr_value(__ptr) { } bool operator()(_Block_pair __bp) const throw() { if (std::less_equal()(_M_ptr_value, __bp.second) && std::greater_equal()(_M_ptr_value, __bp.first)) return true; else return false; } }; // Used to pass a Functor to functions by reference. template class _Functor_Ref : public std::unary_function { _Functor& _M_fref; public: typedef typename _Functor::argument_type argument_type; typedef typename _Functor::result_type result_type; _Functor_Ref(_Functor& __fref) : _M_fref(__fref) { } result_type operator()(argument_type __arg) { return _M_fref(__arg); } }; /** @class _Ffit_finder bitmap_allocator.h bitmap_allocator.h * * @brief The class which acts as a predicate for applying the * first-fit memory allocation policy for the bitmap allocator. */ // _Tp should be a pointer type, and _Alloc is the Allocator for // the vector. template class _Ffit_finder : public std::unary_function, bool> { typedef typename std::pair<_Tp, _Tp> _Block_pair; typedef typename __detail::__mini_vector<_Block_pair> _BPVector; typedef typename _BPVector::difference_type _Counter_type; size_t* _M_pbitmap; _Counter_type _M_data_offset; public: _Ffit_finder() : _M_pbitmap(0), _M_data_offset(0) { } bool operator()(_Block_pair __bp) throw() { // Set the _rover to the last physical location bitmap, // which is the bitmap which belongs to the first free // block. Thus, the bitmaps are in exact reverse order of // the actual memory layout. So, we count down the bitmaps, // which is the same as moving up the memory. // If the used count stored at the start of the Bit Map headers // is equal to the number of Objects that the current Block can // store, then there is definitely no space for another single // object, so just return false. _Counter_type __diff = __detail::__num_bitmaps(__bp); if (*(reinterpret_cast (__bp.first) - (__diff + 1)) == __detail::__num_blocks(__bp)) return false; size_t* __rover = reinterpret_cast(__bp.first) - 1; for (_Counter_type __i = 0; __i < __diff; ++__i) { _M_data_offset = __i; if (*__rover) { _M_pbitmap = __rover; return true; } --__rover; } return false; } size_t* _M_get() const throw() { return _M_pbitmap; } _Counter_type _M_offset() const throw() { return _M_data_offset * size_t(bits_per_block); } }; /** @class _Bitmap_counter bitmap_allocator.h bitmap_allocator.h * * @brief The bitmap counter which acts as the bitmap * manipulator, and manages the bit-manipulation functions and * the searching and identification functions on the bit-map. */ // _Tp should be a pointer type. template class _Bitmap_counter { typedef typename __detail::__mini_vector > _BPVector; typedef typename _BPVector::size_type _Index_type; typedef _Tp pointer; _BPVector& _M_vbp; size_t* _M_curr_bmap; size_t* _M_last_bmap_in_block; _Index_type _M_curr_index; public: // Use the 2nd parameter with care. Make sure that such an // entry exists in the vector before passing that particular // index to this ctor. _Bitmap_counter(_BPVector& Rvbp, long __index = -1) : _M_vbp(Rvbp) { this->_M_reset(__index); } void _M_reset(long __index = -1) throw() { if (__index == -1) { _M_curr_bmap = 0; _M_curr_index = static_cast<_Index_type>(-1); return; } _M_curr_index = __index; _M_curr_bmap = reinterpret_cast (_M_vbp[_M_curr_index].first) - 1; _GLIBCXX_DEBUG_ASSERT(__index <= (long)_M_vbp.size() - 1); _M_last_bmap_in_block = _M_curr_bmap - ((_M_vbp[_M_curr_index].second - _M_vbp[_M_curr_index].first + 1) / size_t(bits_per_block) - 1); } // Dangerous Function! Use with extreme care. Pass to this // function ONLY those values that are known to be correct, // otherwise this will mess up big time. void _M_set_internal_bitmap(size_t* __new_internal_marker) throw() { _M_curr_bmap = __new_internal_marker; } bool _M_finished() const throw() { return(_M_curr_bmap == 0); } _Bitmap_counter& operator++() throw() { if (_M_curr_bmap == _M_last_bmap_in_block) { if (++_M_curr_index == _M_vbp.size()) _M_curr_bmap = 0; else this->_M_reset(_M_curr_index); } else --_M_curr_bmap; return *this; } size_t* _M_get() const throw() { return _M_curr_bmap; } pointer _M_base() const throw() { return _M_vbp[_M_curr_index].first; } _Index_type _M_offset() const throw() { return size_t(bits_per_block) * ((reinterpret_cast(this->_M_base()) - _M_curr_bmap) - 1); } _Index_type _M_where() const throw() { return _M_curr_index; } }; /** @brief Mark a memory address as allocated by re-setting the * corresponding bit in the bit-map. */ inline void __bit_allocate(size_t* __pbmap, size_t __pos) throw() { size_t __mask = 1 << __pos; __mask = ~__mask; *__pbmap &= __mask; } /** @brief Mark a memory address as free by setting the * corresponding bit in the bit-map. */ inline void __bit_free(size_t* __pbmap, size_t __pos) throw() { size_t __mask = 1 << __pos; *__pbmap |= __mask; } } // namespace __detail /** @brief Generic Version of the bsf instruction. */ inline size_t _Bit_scan_forward(size_t __num) { return static_cast(__builtin_ctzl(__num)); } /** @class free_list bitmap_allocator.h bitmap_allocator.h * * @brief The free list class for managing chunks of memory to be * given to and returned by the bitmap_allocator. */ class free_list { public: typedef size_t* value_type; typedef __detail::__mini_vector vector_type; typedef vector_type::iterator iterator; typedef __mutex __mutex_type; private: struct _LT_pointer_compare { bool operator()(const size_t* __pui, const size_t __cui) const throw() { return *__pui < __cui; } }; #if defined __GTHREADS __mutex_type& _M_get_mutex() { static __mutex_type _S_mutex; return _S_mutex; } #endif vector_type& _M_get_free_list() { static vector_type _S_free_list; return _S_free_list; } /** @brief Performs validation of memory based on their size. * * @param __addr The pointer to the memory block to be * validated. * * Validates the memory block passed to this function and * appropriately performs the action of managing the free list of * blocks by adding this block to the free list or deleting this * or larger blocks from the free list. */ void _M_validate(size_t* __addr) throw() { vector_type& __free_list = _M_get_free_list(); const vector_type::size_type __max_size = 64; if (__free_list.size() >= __max_size) { // Ok, the threshold value has been reached. We determine // which block to remove from the list of free blocks. if (*__addr >= *__free_list.back()) { // Ok, the new block is greater than or equal to the // last block in the list of free blocks. We just free // the new block. ::operator delete(static_cast(__addr)); return; } else { // Deallocate the last block in the list of free lists, // and insert the new one in its correct position. ::operator delete(static_cast(__free_list.back())); __free_list.pop_back(); } } // Just add the block to the list of free lists unconditionally. iterator __temp = __detail::__lower_bound (__free_list.begin(), __free_list.end(), *__addr, _LT_pointer_compare()); // We may insert the new free list before _temp; __free_list.insert(__temp, __addr); } /** @brief Decides whether the wastage of memory is acceptable for * the current memory request and returns accordingly. * * @param __block_size The size of the block available in the free * list. * * @param __required_size The required size of the memory block. * * @return true if the wastage incurred is acceptable, else returns * false. */ bool _M_should_i_give(size_t __block_size, size_t __required_size) throw() { const size_t __max_wastage_percentage = 36; if (__block_size >= __required_size && (((__block_size - __required_size) * 100 / __block_size) < __max_wastage_percentage)) return true; else return false; } public: /** @brief This function returns the block of memory to the * internal free list. * * @param __addr The pointer to the memory block that was given * by a call to the _M_get function. */ inline void _M_insert(size_t* __addr) throw() { #if defined __GTHREADS __scoped_lock __bfl_lock(_M_get_mutex()); #endif // Call _M_validate to decide what should be done with // this particular free list. this->_M_validate(reinterpret_cast(__addr) - 1); // See discussion as to why this is 1! } /** @brief This function gets a block of memory of the specified * size from the free list. * * @param __sz The size in bytes of the memory required. * * @return A pointer to the new memory block of size at least * equal to that requested. */ size_t* _M_get(size_t __sz) _GLIBCXX_THROW(std::bad_alloc); /** @brief This function just clears the internal Free List, and * gives back all the memory to the OS. */ void _M_clear(); }; // Forward declare the class. template class bitmap_allocator; // Specialize for void: template<> class bitmap_allocator { public: typedef void* pointer; typedef const void* const_pointer; // Reference-to-void members are impossible. typedef void value_type; template struct rebind { typedef bitmap_allocator<_Tp1> other; }; }; /** * @brief Bitmap Allocator, primary template. * @ingroup allocators */ template class bitmap_allocator : private free_list { public: typedef size_t size_type; typedef ptrdiff_t difference_type; typedef _Tp* pointer; typedef const _Tp* const_pointer; typedef _Tp& reference; typedef const _Tp& const_reference; typedef _Tp value_type; typedef free_list::__mutex_type __mutex_type; template struct rebind { typedef bitmap_allocator<_Tp1> other; }; #if __cplusplus >= 201103L // _GLIBCXX_RESOLVE_LIB_DEFECTS // 2103. propagate_on_container_move_assignment typedef std::true_type propagate_on_container_move_assignment; #endif private: template struct aligned_size { enum { modulus = _BSize % _AlignSize, value = _BSize + (modulus ? _AlignSize - (modulus) : 0) }; }; struct _Alloc_block { char __M_unused[aligned_size::value]; }; typedef typename std::pair<_Alloc_block*, _Alloc_block*> _Block_pair; typedef typename __detail::__mini_vector<_Block_pair> _BPVector; typedef typename _BPVector::iterator _BPiter; template static _BPiter _S_find(_Predicate __p) { _BPiter __first = _S_mem_blocks.begin(); while (__first != _S_mem_blocks.end() && !__p(*__first)) ++__first; return __first; } #if defined _GLIBCXX_DEBUG // Complexity: O(lg(N)). Where, N is the number of block of size // sizeof(value_type). void _S_check_for_free_blocks() throw() { typedef typename __detail::_Ffit_finder<_Alloc_block*> _FFF; _BPiter __bpi = _S_find(_FFF()); _GLIBCXX_DEBUG_ASSERT(__bpi == _S_mem_blocks.end()); } #endif /** @brief Responsible for exponentially growing the internal * memory pool. * * @throw std::bad_alloc. If memory can not be allocated. * * Complexity: O(1), but internally depends upon the * complexity of the function free_list::_M_get. The part where * the bitmap headers are written has complexity: O(X),where X * is the number of blocks of size sizeof(value_type) within * the newly acquired block. Having a tight bound. */ void _S_refill_pool() _GLIBCXX_THROW(std::bad_alloc) { #if defined _GLIBCXX_DEBUG _S_check_for_free_blocks(); #endif const size_t __num_bitmaps = (_S_block_size / size_t(__detail::bits_per_block)); const size_t __size_to_allocate = sizeof(size_t) + _S_block_size * sizeof(_Alloc_block) + __num_bitmaps * sizeof(size_t); size_t* __temp = reinterpret_cast(this->_M_get(__size_to_allocate)); *__temp = 0; ++__temp; // The Header information goes at the Beginning of the Block. _Block_pair __bp = std::make_pair(reinterpret_cast<_Alloc_block*> (__temp + __num_bitmaps), reinterpret_cast<_Alloc_block*> (__temp + __num_bitmaps) + _S_block_size - 1); // Fill the Vector with this information. _S_mem_blocks.push_back(__bp); for (size_t __i = 0; __i < __num_bitmaps; ++__i) __temp[__i] = ~static_cast(0); // 1 Indicates all Free. _S_block_size *= 2; } static _BPVector _S_mem_blocks; static size_t _S_block_size; static __detail::_Bitmap_counter<_Alloc_block*> _S_last_request; static typename _BPVector::size_type _S_last_dealloc_index; #if defined __GTHREADS static __mutex_type _S_mut; #endif public: /** @brief Allocates memory for a single object of size * sizeof(_Tp). * * @throw std::bad_alloc. If memory can not be allocated. * * Complexity: Worst case complexity is O(N), but that * is hardly ever hit. If and when this particular case is * encountered, the next few cases are guaranteed to have a * worst case complexity of O(1)! That's why this function * performs very well on average. You can consider this * function to have a complexity referred to commonly as: * Amortized Constant time. */ pointer _M_allocate_single_object() _GLIBCXX_THROW(std::bad_alloc) { #if defined __GTHREADS __scoped_lock __bit_lock(_S_mut); #endif // The algorithm is something like this: The last_request // variable points to the last accessed Bit Map. When such a // condition occurs, we try to find a free block in the // current bitmap, or succeeding bitmaps until the last bitmap // is reached. If no free block turns up, we resort to First // Fit method. // WARNING: Do not re-order the condition in the while // statement below, because it relies on C++'s short-circuit // evaluation. The return from _S_last_request->_M_get() will // NOT be dereference able if _S_last_request->_M_finished() // returns true. This would inevitably lead to a NULL pointer // dereference if tinkered with. while (_S_last_request._M_finished() == false && (*(_S_last_request._M_get()) == 0)) _S_last_request.operator++(); if (__builtin_expect(_S_last_request._M_finished() == true, false)) { // Fall Back to First Fit algorithm. typedef typename __detail::_Ffit_finder<_Alloc_block*> _FFF; _FFF __fff; _BPiter __bpi = _S_find(__detail::_Functor_Ref<_FFF>(__fff)); if (__bpi != _S_mem_blocks.end()) { // Search was successful. Ok, now mark the first bit from // the right as 0, meaning Allocated. This bit is obtained // by calling _M_get() on __fff. size_t __nz_bit = _Bit_scan_forward(*__fff._M_get()); __detail::__bit_allocate(__fff._M_get(), __nz_bit); _S_last_request._M_reset(__bpi - _S_mem_blocks.begin()); // Now, get the address of the bit we marked as allocated. pointer __ret = reinterpret_cast (__bpi->first + __fff._M_offset() + __nz_bit); size_t* __puse_count = reinterpret_cast (__bpi->first) - (__detail::__num_bitmaps(*__bpi) + 1); ++(*__puse_count); return __ret; } else { // Search was unsuccessful. We Add more memory to the // pool by calling _S_refill_pool(). _S_refill_pool(); // _M_Reset the _S_last_request structure to the first // free block's bit map. _S_last_request._M_reset(_S_mem_blocks.size() - 1); // Now, mark that bit as allocated. } } // _S_last_request holds a pointer to a valid bit map, that // points to a free block in memory. size_t __nz_bit = _Bit_scan_forward(*_S_last_request._M_get()); __detail::__bit_allocate(_S_last_request._M_get(), __nz_bit); pointer __ret = reinterpret_cast (_S_last_request._M_base() + _S_last_request._M_offset() + __nz_bit); size_t* __puse_count = reinterpret_cast (_S_mem_blocks[_S_last_request._M_where()].first) - (__detail:: __num_bitmaps(_S_mem_blocks[_S_last_request._M_where()]) + 1); ++(*__puse_count); return __ret; } /** @brief Deallocates memory that belongs to a single object of * size sizeof(_Tp). * * Complexity: O(lg(N)), but the worst case is not hit * often! This is because containers usually deallocate memory * close to each other and this case is handled in O(1) time by * the deallocate function. */ void _M_deallocate_single_object(pointer __p) throw() { #if defined __GTHREADS __scoped_lock __bit_lock(_S_mut); #endif _Alloc_block* __real_p = reinterpret_cast<_Alloc_block*>(__p); typedef typename _BPVector::iterator _Iterator; typedef typename _BPVector::difference_type _Difference_type; _Difference_type __diff; long __displacement; _GLIBCXX_DEBUG_ASSERT(_S_last_dealloc_index >= 0); __detail::_Inclusive_between<_Alloc_block*> __ibt(__real_p); if (__ibt(_S_mem_blocks[_S_last_dealloc_index])) { _GLIBCXX_DEBUG_ASSERT(_S_last_dealloc_index <= _S_mem_blocks.size() - 1); // Initial Assumption was correct! __diff = _S_last_dealloc_index; __displacement = __real_p - _S_mem_blocks[__diff].first; } else { _Iterator _iter = _S_find(__ibt); _GLIBCXX_DEBUG_ASSERT(_iter != _S_mem_blocks.end()); __diff = _iter - _S_mem_blocks.begin(); __displacement = __real_p - _S_mem_blocks[__diff].first; _S_last_dealloc_index = __diff; } // Get the position of the iterator that has been found. const size_t __rotate = (__displacement % size_t(__detail::bits_per_block)); size_t* __bitmapC = reinterpret_cast (_S_mem_blocks[__diff].first) - 1; __bitmapC -= (__displacement / size_t(__detail::bits_per_block)); __detail::__bit_free(__bitmapC, __rotate); size_t* __puse_count = reinterpret_cast (_S_mem_blocks[__diff].first) - (__detail::__num_bitmaps(_S_mem_blocks[__diff]) + 1); _GLIBCXX_DEBUG_ASSERT(*__puse_count != 0); --(*__puse_count); if (__builtin_expect(*__puse_count == 0, false)) { _S_block_size /= 2; // We can safely remove this block. // _Block_pair __bp = _S_mem_blocks[__diff]; this->_M_insert(__puse_count); _S_mem_blocks.erase(_S_mem_blocks.begin() + __diff); // Reset the _S_last_request variable to reflect the // erased block. We do this to protect future requests // after the last block has been removed from a particular // memory Chunk, which in turn has been returned to the // free list, and hence had been erased from the vector, // so the size of the vector gets reduced by 1. if ((_Difference_type)_S_last_request._M_where() >= __diff--) _S_last_request._M_reset(__diff); // If the Index into the vector of the region of memory // that might hold the next address that will be passed to // deallocated may have been invalidated due to the above // erase procedure being called on the vector, hence we // try to restore this invariant too. if (_S_last_dealloc_index >= _S_mem_blocks.size()) { _S_last_dealloc_index =(__diff != -1 ? __diff : 0); _GLIBCXX_DEBUG_ASSERT(_S_last_dealloc_index >= 0); } } } public: bitmap_allocator() _GLIBCXX_USE_NOEXCEPT { } bitmap_allocator(const bitmap_allocator&) _GLIBCXX_USE_NOEXCEPT { } template bitmap_allocator(const bitmap_allocator<_Tp1>&) _GLIBCXX_USE_NOEXCEPT { } ~bitmap_allocator() _GLIBCXX_USE_NOEXCEPT { } pointer allocate(size_type __n) { if (__n > this->max_size()) std::__throw_bad_alloc(); #if __cpp_aligned_new if (alignof(value_type) > __STDCPP_DEFAULT_NEW_ALIGNMENT__) { const size_type __b = __n * sizeof(value_type); std::align_val_t __al = std::align_val_t(alignof(value_type)); return static_cast(::operator new(__b, __al)); } #endif if (__builtin_expect(__n == 1, true)) return this->_M_allocate_single_object(); else { const size_type __b = __n * sizeof(value_type); return reinterpret_cast(::operator new(__b)); } } pointer allocate(size_type __n, typename bitmap_allocator::const_pointer) { return allocate(__n); } void deallocate(pointer __p, size_type __n) throw() { if (__builtin_expect(__p != 0, true)) { #if __cpp_aligned_new // Types with extended alignment are handled by operator delete. if (alignof(value_type) > __STDCPP_DEFAULT_NEW_ALIGNMENT__) { ::operator delete(__p, std::align_val_t(alignof(value_type))); return; } #endif if (__builtin_expect(__n == 1, true)) this->_M_deallocate_single_object(__p); else ::operator delete(__p); } } pointer address(reference __r) const _GLIBCXX_NOEXCEPT { return std::__addressof(__r); } const_pointer address(const_reference __r) const _GLIBCXX_NOEXCEPT { return std::__addressof(__r); } size_type max_size() const _GLIBCXX_USE_NOEXCEPT { return size_type(-1) / sizeof(value_type); } #if __cplusplus >= 201103L template void construct(_Up* __p, _Args&&... __args) { ::new((void *)__p) _Up(std::forward<_Args>(__args)...); } template void destroy(_Up* __p) { __p->~_Up(); } #else void construct(pointer __p, const_reference __data) { ::new((void *)__p) value_type(__data); } void destroy(pointer __p) { __p->~value_type(); } #endif }; template bool operator==(const bitmap_allocator<_Tp1>&, const bitmap_allocator<_Tp2>&) throw() { return true; } template bool operator!=(const bitmap_allocator<_Tp1>&, const bitmap_allocator<_Tp2>&) throw() { return false; } // Static member definitions. template typename bitmap_allocator<_Tp>::_BPVector bitmap_allocator<_Tp>::_S_mem_blocks; template size_t bitmap_allocator<_Tp>::_S_block_size = 2 * size_t(__detail::bits_per_block); template typename bitmap_allocator<_Tp>::_BPVector::size_type bitmap_allocator<_Tp>::_S_last_dealloc_index = 0; template __detail::_Bitmap_counter ::_Alloc_block*> bitmap_allocator<_Tp>::_S_last_request(_S_mem_blocks); #if defined __GTHREADS template typename bitmap_allocator<_Tp>::__mutex_type bitmap_allocator<_Tp>::_S_mut; #endif _GLIBCXX_END_NAMESPACE_VERSION } // namespace __gnu_cxx #endif PKNd]t 8/ext/iteratornu[// HP/SGI iterator extensions -*- C++ -*- // Copyright (C) 2001-2018 Free Software Foundation, Inc. // // This file is part of the GNU ISO C++ Library. This library is free // software; you can redistribute it and/or modify it under the // terms of the GNU General Public License as published by the // Free Software Foundation; either version 3, or (at your option) // any later version. // This library is distributed in the hope that it will be useful, // but WITHOUT ANY WARRANTY; without even the implied warranty of // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the // GNU General Public License for more details. // Under Section 7 of GPL version 3, you are granted additional // permissions described in the GCC Runtime Library Exception, version // 3.1, as published by the Free Software Foundation. // You should have received a copy of the GNU General Public License and // a copy of the GCC Runtime Library Exception along with this program; // see the files COPYING3 and COPYING.RUNTIME respectively. If not, see // . /* * * Copyright (c) 1994 * Hewlett-Packard Company * * Permission to use, copy, modify, distribute and sell this software * and its documentation for any purpose is hereby granted without fee, * provided that the above copyright notice appear in all copies and * that both that copyright notice and this permission notice appear * in supporting documentation. Hewlett-Packard Company makes no * representations about the suitability of this software for any * purpose. It is provided "as is" without express or implied warranty. * * * Copyright (c) 1996-1998 * Silicon Graphics Computer Systems, Inc. * * Permission to use, copy, modify, distribute and sell this software * and its documentation for any purpose is hereby granted without fee, * provided that the above copyright notice appear in all copies and * that both that copyright notice and this permission notice appear * in supporting documentation. Silicon Graphics makes no * representations about the suitability of this software for any * purpose. It is provided "as is" without express or implied warranty. */ /** @file ext/iterator * This file is a GNU extension to the Standard C++ Library (possibly * containing extensions from the HP/SGI STL subset). */ #ifndef _EXT_ITERATOR #define _EXT_ITERATOR 1 #pragma GCC system_header #include #include namespace __gnu_cxx _GLIBCXX_VISIBILITY(default) { _GLIBCXX_BEGIN_NAMESPACE_VERSION // There are two signatures for distance. In addition to the one // taking two iterators and returning a result, there is another // taking two iterators and a reference-to-result variable, and // returning nothing. The latter seems to be an SGI extension. // -- pedwards template inline void __distance(_InputIterator __first, _InputIterator __last, _Distance& __n, std::input_iterator_tag) { // concept requirements __glibcxx_function_requires(_InputIteratorConcept<_InputIterator>) while (__first != __last) { ++__first; ++__n; } } template inline void __distance(_RandomAccessIterator __first, _RandomAccessIterator __last, _Distance& __n, std::random_access_iterator_tag) { // concept requirements __glibcxx_function_requires(_RandomAccessIteratorConcept< _RandomAccessIterator>) __n += __last - __first; } /** * This is an SGI extension. * @ingroup SGIextensions * @doctodo */ template inline void distance(_InputIterator __first, _InputIterator __last, _Distance& __n) { // concept requirements -- taken care of in __distance __distance(__first, __last, __n, std::__iterator_category(__first)); } _GLIBCXX_END_NAMESPACE_VERSION } // namespace #endif PKNd]8/ext/type_traits.hnu[// -*- C++ -*- // Copyright (C) 2005-2018 Free Software Foundation, Inc. // // This file is part of the GNU ISO C++ Library. This library is free // software; you can redistribute it and/or modify it under the terms // of the GNU General Public License as published by the Free Software // Foundation; either version 3, or (at your option) any later // version. // This library is distributed in the hope that it will be useful, but // WITHOUT ANY WARRANTY; without even the implied warranty of // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU // General Public License for more details. // Under Section 7 of GPL version 3, you are granted additional // permissions described in the GCC Runtime Library Exception, version // 3.1, as published by the Free Software Foundation. // You should have received a copy of the GNU General Public License and // a copy of the GCC Runtime Library Exception along with this program; // see the files COPYING3 and COPYING.RUNTIME respectively. If not, see // . /** @file ext/type_traits.h * This file is a GNU extension to the Standard C++ Library. */ #ifndef _EXT_TYPE_TRAITS #define _EXT_TYPE_TRAITS 1 #pragma GCC system_header #include #include extern "C++" { namespace __gnu_cxx _GLIBCXX_VISIBILITY(default) { _GLIBCXX_BEGIN_NAMESPACE_VERSION // Define a nested type if some predicate holds. template struct __enable_if { }; template struct __enable_if { typedef _Tp __type; }; // Conditional expression for types. If true, first, if false, second. template struct __conditional_type { typedef _Iftrue __type; }; template struct __conditional_type { typedef _Iffalse __type; }; // Given an integral builtin type, return the corresponding unsigned type. template struct __add_unsigned { private: typedef __enable_if::__value, _Tp> __if_type; public: typedef typename __if_type::__type __type; }; template<> struct __add_unsigned { typedef unsigned char __type; }; template<> struct __add_unsigned { typedef unsigned char __type; }; template<> struct __add_unsigned { typedef unsigned short __type; }; template<> struct __add_unsigned { typedef unsigned int __type; }; template<> struct __add_unsigned { typedef unsigned long __type; }; template<> struct __add_unsigned { typedef unsigned long long __type; }; // Declare but don't define. template<> struct __add_unsigned; template<> struct __add_unsigned; // Given an integral builtin type, return the corresponding signed type. template struct __remove_unsigned { private: typedef __enable_if::__value, _Tp> __if_type; public: typedef typename __if_type::__type __type; }; template<> struct __remove_unsigned { typedef signed char __type; }; template<> struct __remove_unsigned { typedef signed char __type; }; template<> struct __remove_unsigned { typedef short __type; }; template<> struct __remove_unsigned { typedef int __type; }; template<> struct __remove_unsigned { typedef long __type; }; template<> struct __remove_unsigned { typedef long long __type; }; // Declare but don't define. template<> struct __remove_unsigned; template<> struct __remove_unsigned; // For use in string and vstring. template inline bool __is_null_pointer(_Type* __ptr) { return __ptr == 0; } template inline bool __is_null_pointer(_Type) { return false; } #if __cplusplus >= 201103L inline bool __is_null_pointer(std::nullptr_t) { return true; } #endif // For complex and cmath template::__value> struct __promote { typedef double __type; }; // No nested __type member for non-integer non-floating point types, // allows this type to be used for SFINAE to constrain overloads in // and to only the intended types. template struct __promote<_Tp, false> { }; template<> struct __promote { typedef long double __type; }; template<> struct __promote { typedef double __type; }; template<> struct __promote { typedef float __type; }; template::__type, typename _Up2 = typename __promote<_Up>::__type> struct __promote_2 { typedef __typeof__(_Tp2() + _Up2()) __type; }; template::__type, typename _Up2 = typename __promote<_Up>::__type, typename _Vp2 = typename __promote<_Vp>::__type> struct __promote_3 { typedef __typeof__(_Tp2() + _Up2() + _Vp2()) __type; }; template::__type, typename _Up2 = typename __promote<_Up>::__type, typename _Vp2 = typename __promote<_Vp>::__type, typename _Wp2 = typename __promote<_Wp>::__type> struct __promote_4 { typedef __typeof__(_Tp2() + _Up2() + _Vp2() + _Wp2()) __type; }; _GLIBCXX_END_NAMESPACE_VERSION } // namespace } // extern "C++" #endif PKNd]2  8/ext/string_conversions.hnu[// String Conversions -*- C++ -*- // Copyright (C) 2008-2018 Free Software Foundation, Inc. // // This file is part of the GNU ISO C++ Library. This library is free // software; you can redistribute it and/or modify it under the // terms of the GNU General Public License as published by the // Free Software Foundation; either version 3, or (at your option) // any later version. // This library is distributed in the hope that it will be useful, // but WITHOUT ANY WARRANTY; without even the implied warranty of // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the // GNU General Public License for more details. // Under Section 7 of GPL version 3, you are granted additional // permissions described in the GCC Runtime Library Exception, version // 3.1, as published by the Free Software Foundation. // You should have received a copy of the GNU General Public License and // a copy of the GCC Runtime Library Exception along with this program; // see the files COPYING3 and COPYING.RUNTIME respectively. If not, see // . /** @file ext/string_conversions.h * This file is a GNU extension to the Standard C++ Library. */ #ifndef _STRING_CONVERSIONS_H #define _STRING_CONVERSIONS_H 1 #pragma GCC system_header #if __cplusplus < 201103L # include #else #include #include #include #include #include #include #include namespace __gnu_cxx _GLIBCXX_VISIBILITY(default) { _GLIBCXX_BEGIN_NAMESPACE_VERSION // Helper for all the sto* functions. template _Ret __stoa(_TRet (*__convf) (const _CharT*, _CharT**, _Base...), const char* __name, const _CharT* __str, std::size_t* __idx, _Base... __base) { _Ret __ret; _CharT* __endptr; struct _Save_errno { _Save_errno() : _M_errno(errno) { errno = 0; } ~_Save_errno() { if (errno == 0) errno = _M_errno; } int _M_errno; } const __save_errno; struct _Range_chk { static bool _S_chk(_TRet, std::false_type) { return false; } static bool _S_chk(_TRet __val, std::true_type) // only called when _Ret is int { return __val < _TRet(__numeric_traits::__min) || __val > _TRet(__numeric_traits::__max); } }; const _TRet __tmp = __convf(__str, &__endptr, __base...); if (__endptr == __str) std::__throw_invalid_argument(__name); else if (errno == ERANGE || _Range_chk::_S_chk(__tmp, std::is_same<_Ret, int>{})) std::__throw_out_of_range(__name); else __ret = __tmp; if (__idx) *__idx = __endptr - __str; return __ret; } // Helper for the to_string / to_wstring functions. template _String __to_xstring(int (*__convf) (_CharT*, std::size_t, const _CharT*, __builtin_va_list), std::size_t __n, const _CharT* __fmt, ...) { // XXX Eventually the result should be constructed in-place in // the __cxx11 string, likely with the help of internal hooks. _CharT* __s = static_cast<_CharT*>(__builtin_alloca(sizeof(_CharT) * __n)); __builtin_va_list __args; __builtin_va_start(__args, __fmt); const int __len = __convf(__s, __n, __fmt, __args); __builtin_va_end(__args); return _String(__s, __s + __len); } _GLIBCXX_END_NAMESPACE_VERSION } // namespace #endif // C++11 #endif // _STRING_CONVERSIONS_H PKNd]oEoE8/ext/hash_mapnu[// Hashing map implementation -*- C++ -*- // Copyright (C) 2001-2018 Free Software Foundation, Inc. // // This file is part of the GNU ISO C++ Library. This library is free // software; you can redistribute it and/or modify it under the // terms of the GNU General Public License as published by the // Free Software Foundation; either version 3, or (at your option) // any later version. // This library is distributed in the hope that it will be useful, // but WITHOUT ANY WARRANTY; without even the implied warranty of // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the // GNU General Public License for more details. // Under Section 7 of GPL version 3, you are granted additional // permissions described in the GCC Runtime Library Exception, version // 3.1, as published by the Free Software Foundation. // You should have received a copy of the GNU General Public License and // a copy of the GCC Runtime Library Exception along with this program; // see the files COPYING3 and COPYING.RUNTIME respectively. If not, see // . /* * Copyright (c) 1996 * Silicon Graphics Computer Systems, Inc. * * Permission to use, copy, modify, distribute and sell this software * and its documentation for any purpose is hereby granted without fee, * provided that the above copyright notice appear in all copies and * that both that copyright notice and this permission notice appear * in supporting documentation. Silicon Graphics makes no * representations about the suitability of this software for any * purpose. It is provided "as is" without express or implied warranty. * * * Copyright (c) 1994 * Hewlett-Packard Company * * Permission to use, copy, modify, distribute and sell this software * and its documentation for any purpose is hereby granted without fee, * provided that the above copyright notice appear in all copies and * that both that copyright notice and this permission notice appear * in supporting documentation. Hewlett-Packard Company makes no * representations about the suitability of this software for any * purpose. It is provided "as is" without express or implied warranty. * */ /** @file backward/hash_map * This file is a GNU extension to the Standard C++ Library (possibly * containing extensions from the HP/SGI STL subset). */ #ifndef _BACKWARD_HASH_MAP #define _BACKWARD_HASH_MAP 1 #ifndef _GLIBCXX_PERMIT_BACKWARD_HASH #include "backward_warning.h" #endif #include #include #include namespace __gnu_cxx _GLIBCXX_VISIBILITY(default) { _GLIBCXX_BEGIN_NAMESPACE_VERSION using std::equal_to; using std::allocator; using std::pair; using std::_Select1st; /** * This is an SGI extension. * @ingroup SGIextensions * @doctodo */ template, class _EqualKey = equal_to<_Key>, class _Alloc = allocator<_Tp> > class hash_map { private: typedef hashtable,_Key, _HashFn, _Select1st >, _EqualKey, _Alloc> _Ht; _Ht _M_ht; public: typedef typename _Ht::key_type key_type; typedef _Tp data_type; typedef _Tp mapped_type; typedef typename _Ht::value_type value_type; typedef typename _Ht::hasher hasher; typedef typename _Ht::key_equal key_equal; typedef typename _Ht::size_type size_type; typedef typename _Ht::difference_type difference_type; typedef typename _Ht::pointer pointer; typedef typename _Ht::const_pointer const_pointer; typedef typename _Ht::reference reference; typedef typename _Ht::const_reference const_reference; typedef typename _Ht::iterator iterator; typedef typename _Ht::const_iterator const_iterator; typedef typename _Ht::allocator_type allocator_type; hasher hash_funct() const { return _M_ht.hash_funct(); } key_equal key_eq() const { return _M_ht.key_eq(); } allocator_type get_allocator() const { return _M_ht.get_allocator(); } hash_map() : _M_ht(100, hasher(), key_equal(), allocator_type()) {} explicit hash_map(size_type __n) : _M_ht(__n, hasher(), key_equal(), allocator_type()) {} hash_map(size_type __n, const hasher& __hf) : _M_ht(__n, __hf, key_equal(), allocator_type()) {} hash_map(size_type __n, const hasher& __hf, const key_equal& __eql, const allocator_type& __a = allocator_type()) : _M_ht(__n, __hf, __eql, __a) {} template hash_map(_InputIterator __f, _InputIterator __l) : _M_ht(100, hasher(), key_equal(), allocator_type()) { _M_ht.insert_unique(__f, __l); } template hash_map(_InputIterator __f, _InputIterator __l, size_type __n) : _M_ht(__n, hasher(), key_equal(), allocator_type()) { _M_ht.insert_unique(__f, __l); } template hash_map(_InputIterator __f, _InputIterator __l, size_type __n, const hasher& __hf) : _M_ht(__n, __hf, key_equal(), allocator_type()) { _M_ht.insert_unique(__f, __l); } template hash_map(_InputIterator __f, _InputIterator __l, size_type __n, const hasher& __hf, const key_equal& __eql, const allocator_type& __a = allocator_type()) : _M_ht(__n, __hf, __eql, __a) { _M_ht.insert_unique(__f, __l); } size_type size() const { return _M_ht.size(); } size_type max_size() const { return _M_ht.max_size(); } bool empty() const { return _M_ht.empty(); } void swap(hash_map& __hs) { _M_ht.swap(__hs._M_ht); } template friend bool operator== (const hash_map<_K1, _T1, _HF, _EqK, _Al>&, const hash_map<_K1, _T1, _HF, _EqK, _Al>&); iterator begin() { return _M_ht.begin(); } iterator end() { return _M_ht.end(); } const_iterator begin() const { return _M_ht.begin(); } const_iterator end() const { return _M_ht.end(); } pair insert(const value_type& __obj) { return _M_ht.insert_unique(__obj); } template void insert(_InputIterator __f, _InputIterator __l) { _M_ht.insert_unique(__f, __l); } pair insert_noresize(const value_type& __obj) { return _M_ht.insert_unique_noresize(__obj); } iterator find(const key_type& __key) { return _M_ht.find(__key); } const_iterator find(const key_type& __key) const { return _M_ht.find(__key); } _Tp& operator[](const key_type& __key) { return _M_ht.find_or_insert(value_type(__key, _Tp())).second; } size_type count(const key_type& __key) const { return _M_ht.count(__key); } pair equal_range(const key_type& __key) { return _M_ht.equal_range(__key); } pair equal_range(const key_type& __key) const { return _M_ht.equal_range(__key); } size_type erase(const key_type& __key) {return _M_ht.erase(__key); } void erase(iterator __it) { _M_ht.erase(__it); } void erase(iterator __f, iterator __l) { _M_ht.erase(__f, __l); } void clear() { _M_ht.clear(); } void resize(size_type __hint) { _M_ht.resize(__hint); } size_type bucket_count() const { return _M_ht.bucket_count(); } size_type max_bucket_count() const { return _M_ht.max_bucket_count(); } size_type elems_in_bucket(size_type __n) const { return _M_ht.elems_in_bucket(__n); } }; template inline bool operator==(const hash_map<_Key, _Tp, _HashFn, _EqlKey, _Alloc>& __hm1, const hash_map<_Key, _Tp, _HashFn, _EqlKey, _Alloc>& __hm2) { return __hm1._M_ht == __hm2._M_ht; } template inline bool operator!=(const hash_map<_Key, _Tp, _HashFn, _EqlKey, _Alloc>& __hm1, const hash_map<_Key, _Tp, _HashFn, _EqlKey, _Alloc>& __hm2) { return !(__hm1 == __hm2); } template inline void swap(hash_map<_Key, _Tp, _HashFn, _EqlKey, _Alloc>& __hm1, hash_map<_Key, _Tp, _HashFn, _EqlKey, _Alloc>& __hm2) { __hm1.swap(__hm2); } /** * This is an SGI extension. * @ingroup SGIextensions * @doctodo */ template, class _EqualKey = equal_to<_Key>, class _Alloc = allocator<_Tp> > class hash_multimap { // concept requirements __glibcxx_class_requires(_Key, _SGIAssignableConcept) __glibcxx_class_requires(_Tp, _SGIAssignableConcept) __glibcxx_class_requires3(_HashFn, size_t, _Key, _UnaryFunctionConcept) __glibcxx_class_requires3(_EqualKey, _Key, _Key, _BinaryPredicateConcept) private: typedef hashtable, _Key, _HashFn, _Select1st >, _EqualKey, _Alloc> _Ht; _Ht _M_ht; public: typedef typename _Ht::key_type key_type; typedef _Tp data_type; typedef _Tp mapped_type; typedef typename _Ht::value_type value_type; typedef typename _Ht::hasher hasher; typedef typename _Ht::key_equal key_equal; typedef typename _Ht::size_type size_type; typedef typename _Ht::difference_type difference_type; typedef typename _Ht::pointer pointer; typedef typename _Ht::const_pointer const_pointer; typedef typename _Ht::reference reference; typedef typename _Ht::const_reference const_reference; typedef typename _Ht::iterator iterator; typedef typename _Ht::const_iterator const_iterator; typedef typename _Ht::allocator_type allocator_type; hasher hash_funct() const { return _M_ht.hash_funct(); } key_equal key_eq() const { return _M_ht.key_eq(); } allocator_type get_allocator() const { return _M_ht.get_allocator(); } hash_multimap() : _M_ht(100, hasher(), key_equal(), allocator_type()) {} explicit hash_multimap(size_type __n) : _M_ht(__n, hasher(), key_equal(), allocator_type()) {} hash_multimap(size_type __n, const hasher& __hf) : _M_ht(__n, __hf, key_equal(), allocator_type()) {} hash_multimap(size_type __n, const hasher& __hf, const key_equal& __eql, const allocator_type& __a = allocator_type()) : _M_ht(__n, __hf, __eql, __a) {} template hash_multimap(_InputIterator __f, _InputIterator __l) : _M_ht(100, hasher(), key_equal(), allocator_type()) { _M_ht.insert_equal(__f, __l); } template hash_multimap(_InputIterator __f, _InputIterator __l, size_type __n) : _M_ht(__n, hasher(), key_equal(), allocator_type()) { _M_ht.insert_equal(__f, __l); } template hash_multimap(_InputIterator __f, _InputIterator __l, size_type __n, const hasher& __hf) : _M_ht(__n, __hf, key_equal(), allocator_type()) { _M_ht.insert_equal(__f, __l); } template hash_multimap(_InputIterator __f, _InputIterator __l, size_type __n, const hasher& __hf, const key_equal& __eql, const allocator_type& __a = allocator_type()) : _M_ht(__n, __hf, __eql, __a) { _M_ht.insert_equal(__f, __l); } size_type size() const { return _M_ht.size(); } size_type max_size() const { return _M_ht.max_size(); } bool empty() const { return _M_ht.empty(); } void swap(hash_multimap& __hs) { _M_ht.swap(__hs._M_ht); } template friend bool operator==(const hash_multimap<_K1, _T1, _HF, _EqK, _Al>&, const hash_multimap<_K1, _T1, _HF, _EqK, _Al>&); iterator begin() { return _M_ht.begin(); } iterator end() { return _M_ht.end(); } const_iterator begin() const { return _M_ht.begin(); } const_iterator end() const { return _M_ht.end(); } iterator insert(const value_type& __obj) { return _M_ht.insert_equal(__obj); } template void insert(_InputIterator __f, _InputIterator __l) { _M_ht.insert_equal(__f,__l); } iterator insert_noresize(const value_type& __obj) { return _M_ht.insert_equal_noresize(__obj); } iterator find(const key_type& __key) { return _M_ht.find(__key); } const_iterator find(const key_type& __key) const { return _M_ht.find(__key); } size_type count(const key_type& __key) const { return _M_ht.count(__key); } pair equal_range(const key_type& __key) { return _M_ht.equal_range(__key); } pair equal_range(const key_type& __key) const { return _M_ht.equal_range(__key); } size_type erase(const key_type& __key) { return _M_ht.erase(__key); } void erase(iterator __it) { _M_ht.erase(__it); } void erase(iterator __f, iterator __l) { _M_ht.erase(__f, __l); } void clear() { _M_ht.clear(); } void resize(size_type __hint) { _M_ht.resize(__hint); } size_type bucket_count() const { return _M_ht.bucket_count(); } size_type max_bucket_count() const { return _M_ht.max_bucket_count(); } size_type elems_in_bucket(size_type __n) const { return _M_ht.elems_in_bucket(__n); } }; template inline bool operator==(const hash_multimap<_Key, _Tp, _HF, _EqKey, _Alloc>& __hm1, const hash_multimap<_Key, _Tp, _HF, _EqKey, _Alloc>& __hm2) { return __hm1._M_ht == __hm2._M_ht; } template inline bool operator!=(const hash_multimap<_Key, _Tp, _HF, _EqKey, _Alloc>& __hm1, const hash_multimap<_Key, _Tp, _HF, _EqKey, _Alloc>& __hm2) { return !(__hm1 == __hm2); } template inline void swap(hash_multimap<_Key, _Tp, _HashFn, _EqlKey, _Alloc>& __hm1, hash_multimap<_Key, _Tp, _HashFn, _EqlKey, _Alloc>& __hm2) { __hm1.swap(__hm2); } _GLIBCXX_END_NAMESPACE_VERSION } // namespace namespace std _GLIBCXX_VISIBILITY(default) { _GLIBCXX_BEGIN_NAMESPACE_VERSION // Specialization of insert_iterator so that it will work for hash_map // and hash_multimap. template class insert_iterator<__gnu_cxx::hash_map<_Key, _Tp, _HashFn, _EqKey, _Alloc> > { protected: typedef __gnu_cxx::hash_map<_Key, _Tp, _HashFn, _EqKey, _Alloc> _Container; _Container* container; public: typedef _Container container_type; typedef output_iterator_tag iterator_category; typedef void value_type; typedef void difference_type; typedef void pointer; typedef void reference; insert_iterator(_Container& __x) : container(&__x) {} insert_iterator(_Container& __x, typename _Container::iterator) : container(&__x) {} insert_iterator<_Container>& operator=(const typename _Container::value_type& __value) { container->insert(__value); return *this; } insert_iterator<_Container>& operator*() { return *this; } insert_iterator<_Container>& operator++() { return *this; } insert_iterator<_Container>& operator++(int) { return *this; } }; template class insert_iterator<__gnu_cxx::hash_multimap<_Key, _Tp, _HashFn, _EqKey, _Alloc> > { protected: typedef __gnu_cxx::hash_multimap<_Key, _Tp, _HashFn, _EqKey, _Alloc> _Container; _Container* container; typename _Container::iterator iter; public: typedef _Container container_type; typedef output_iterator_tag iterator_category; typedef void value_type; typedef void difference_type; typedef void pointer; typedef void reference; insert_iterator(_Container& __x) : container(&__x) {} insert_iterator(_Container& __x, typename _Container::iterator) : container(&__x) {} insert_iterator<_Container>& operator=(const typename _Container::value_type& __value) { container->insert(__value); return *this; } insert_iterator<_Container>& operator*() { return *this; } insert_iterator<_Container>& operator++() { return *this; } insert_iterator<_Container>& operator++(int) { return *this; } }; _GLIBCXX_END_NAMESPACE_VERSION } // namespace #endif PKNd] `@`@8/ext/typelist.hnu[// -*- C++ -*- // Copyright (C) 2005-2018 Free Software Foundation, Inc. // // This file is part of the GNU ISO C++ Library. This library is free // software; you can redistribute it and/or modify it under the // terms of the GNU General Public License as published by the // Free Software Foundation; either version 3, or (at your option) // any later version. // This library is distributed in the hope that it will be useful, // but WITHOUT ANY WARRANTY; without even the implied warranty of // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the // GNU General Public License for more details. // Under Section 7 of GPL version 3, you are granted additional // permissions described in the GCC Runtime Library Exception, version // 3.1, as published by the Free Software Foundation. // You should have received a copy of the GNU General Public License and // a copy of the GCC Runtime Library Exception along with this program; // see the files COPYING3 and COPYING.RUNTIME respectively. If not, see // . // Copyright (C) 2004 Ami Tavory and Vladimir Dreizin, IBM-HRL. // Permission to use, copy, modify, sell, and distribute this software // is hereby granted without fee, provided that the above copyright // notice appears in all copies, and that both that copyright notice and // this permission notice appear in supporting documentation. None of // the above authors, nor IBM Haifa Research Laboratories, make any // representation about the suitability of this software for any // purpose. It is provided "as is" without express or implied warranty. /** * @file ext/typelist.h * This file is a GNU extension to the Standard C++ Library. * * Contains typelist_chain definitions. * Typelists are an idea by Andrei Alexandrescu. */ #ifndef _TYPELIST_H #define _TYPELIST_H 1 #include namespace __gnu_cxx _GLIBCXX_VISIBILITY(default) { _GLIBCXX_BEGIN_NAMESPACE_VERSION /** @namespace __gnu_cxx::typelist * @brief GNU typelist extensions for public compile-time use. */ namespace typelist { struct null_type { }; template struct node { typedef Root root; }; // Forward declarations of functors. template struct chain { typedef Hd head; typedef Typelist tail; }; // Apply all typelist types to unary functor. template void apply(Fn&, Typelist); /// Apply all typelist types to generator functor. template void apply_generator(Gn&, Typelist); // Apply all typelist types and values to generator functor. template void apply_generator(Gn&, TypelistT, TypelistV); template struct append; template struct append_typelist; template struct contains; template class Pred> struct filter; template struct at_index; template class Transform> struct transform; template struct flatten; template struct from_first; template struct create1; template struct create2; template struct create3; template struct create4; template struct create5; template struct create6; namespace detail { template struct apply_; template struct apply_ > { void operator()(Fn& f) { f.operator()(Hd()); apply_ next; next(f); } }; template struct apply_ { void operator()(Fn&) { } }; template struct apply_generator1_; template struct apply_generator1_ > { void operator()(Gn& g) { g.template operator()(); apply_generator1_ next; next(g); } }; template struct apply_generator1_ { void operator()(Gn&) { } }; template struct apply_generator2_; template struct apply_generator2_, chain > { void operator()(Gn& g) { g.template operator()(); apply_generator2_ next; next(g); } }; template struct apply_generator2_ { void operator()(Gn&) { } }; template struct append_; template struct append_, Typelist_Chain> { private: typedef append_ append_type; public: typedef chain type; }; template struct append_ { typedef Typelist_Chain type; }; template struct append_ { typedef Typelist_Chain type; }; template<> struct append_ { typedef null_type type; }; template struct append_typelist_; template struct append_typelist_ > { typedef chain type; }; template struct append_typelist_ > { private: typedef typename append_typelist_::type rest_type; public: typedef typename append >::type::root type; }; template struct contains_; template struct contains_ { enum { value = false }; }; template struct contains_, T> { enum { value = contains_::value }; }; template struct contains_, T> { enum { value = true }; }; template class Pred> struct chain_filter_; template class Pred> struct chain_filter_ { typedef null_type type; }; template class Pred> struct chain_filter_, Pred> { private: enum { include_hd = Pred::value }; typedef typename chain_filter_::type rest_type; typedef chain chain_type; public: typedef typename __conditional_type::__type type; }; template struct chain_at_index_; template struct chain_at_index_, 0> { typedef Hd type; }; template struct chain_at_index_, i> { typedef typename chain_at_index_::type type; }; template class Transform> struct chain_transform_; template class Transform> struct chain_transform_ { typedef null_type type; }; template class Transform> struct chain_transform_, Transform> { private: typedef typename chain_transform_::type rest_type; typedef typename Transform::type transform_type; public: typedef chain type; }; template struct chain_flatten_; template struct chain_flatten_ > { typedef typename Hd_Tl::root type; }; template struct chain_flatten_ > { private: typedef typename chain_flatten_::type rest_type; typedef append > append_type; public: typedef typename append_type::type::root type; }; } // namespace detail #define _GLIBCXX_TYPELIST_CHAIN1(X0) __gnu_cxx::typelist::chain #define _GLIBCXX_TYPELIST_CHAIN2(X0, X1) __gnu_cxx::typelist::chain #define _GLIBCXX_TYPELIST_CHAIN3(X0, X1, X2) __gnu_cxx::typelist::chain #define _GLIBCXX_TYPELIST_CHAIN4(X0, X1, X2, X3) __gnu_cxx::typelist::chain #define _GLIBCXX_TYPELIST_CHAIN5(X0, X1, X2, X3, X4) __gnu_cxx::typelist::chain #define _GLIBCXX_TYPELIST_CHAIN6(X0, X1, X2, X3, X4, X5) __gnu_cxx::typelist::chain #define _GLIBCXX_TYPELIST_CHAIN7(X0, X1, X2, X3, X4, X5, X6) __gnu_cxx::typelist::chain #define _GLIBCXX_TYPELIST_CHAIN8(X0, X1, X2, X3, X4, X5, X6, X7) __gnu_cxx::typelist::chain #define _GLIBCXX_TYPELIST_CHAIN9(X0, X1, X2, X3, X4, X5, X6, X7, X8) __gnu_cxx::typelist::chain #define _GLIBCXX_TYPELIST_CHAIN10(X0, X1, X2, X3, X4, X5, X6, X7, X8, X9) __gnu_cxx::typelist::chain #define _GLIBCXX_TYPELIST_CHAIN11(X0, X1, X2, X3, X4, X5, X6, X7, X8, X9, X10) __gnu_cxx::typelist::chain #define _GLIBCXX_TYPELIST_CHAIN12(X0, X1, X2, X3, X4, X5, X6, X7, X8, X9, X10, X11) __gnu_cxx::typelist::chain #define _GLIBCXX_TYPELIST_CHAIN13(X0, X1, X2, X3, X4, X5, X6, X7, X8, X9, X10, X11, X12) __gnu_cxx::typelist::chain #define _GLIBCXX_TYPELIST_CHAIN14(X0, X1, X2, X3, X4, X5, X6, X7, X8, X9, X10, X11, X12, X13) __gnu_cxx::typelist::chain #define _GLIBCXX_TYPELIST_CHAIN15(X0, X1, X2, X3, X4, X5, X6, X7, X8, X9, X10, X11, X12, X13, X14) __gnu_cxx::typelist::chain #define _GLIBCXX_TYPELIST_CHAIN16(X0, X1, X2, X3, X4, X5, X6, X7, X8, X9, X10, X11, X12, X13, X14, X15) __gnu_cxx::typelist::chain #define _GLIBCXX_TYPELIST_CHAIN17(X0, X1, X2, X3, X4, X5, X6, X7, X8, X9, X10, X11, X12, X13, X14, X15, X16) __gnu_cxx::typelist::chain #define _GLIBCXX_TYPELIST_CHAIN18(X0, X1, X2, X3, X4, X5, X6, X7, X8, X9, X10, X11, X12, X13, X14, X15, X16, X17) __gnu_cxx::typelist::chain #define _GLIBCXX_TYPELIST_CHAIN19(X0, X1, X2, X3, X4, X5, X6, X7, X8, X9, X10, X11, X12, X13, X14, X15, X16, X17, X18) __gnu_cxx::typelist::chain #define _GLIBCXX_TYPELIST_CHAIN20(X0, X1, X2, X3, X4, X5, X6, X7, X8, X9, X10, X11, X12, X13, X14, X15, X16, X17, X18, X19) __gnu_cxx::typelist::chain template void apply(Fn& fn, Typelist) { detail::apply_ a; a(fn); } template void apply_generator(Fn& fn, Typelist) { detail::apply_generator1_ a; a(fn); } template void apply_generator(Fn& fn, TypelistT, TypelistV) { typedef typename TypelistT::root rootT; typedef typename TypelistV::root rootV; detail::apply_generator2_ a; a(fn); } template struct append { private: typedef typename Typelist0::root root0_type; typedef typename Typelist1::root root1_type; typedef detail::append_ append_type; public: typedef node type; }; template struct append_typelist { private: typedef typename Typelist_Typelist::root root_type; typedef detail::append_typelist_ append_type; public: typedef node type; }; template struct contains { private: typedef typename Typelist::root root_type; public: enum { value = detail::contains_::value }; }; template class Pred> struct filter { private: typedef typename Typelist::root root_type; typedef detail::chain_filter_ filter_type; public: typedef node type; }; template struct at_index { private: typedef typename Typelist::root root_type; typedef detail::chain_at_index_ index_type; public: typedef typename index_type::type type; }; template class Transform> struct transform { private: typedef typename Typelist::root root_type; typedef detail::chain_transform_ transform_type; public: typedef node type; }; template struct flatten { private: typedef typename Typelist_Typelist::root root_type; typedef typename detail::chain_flatten_::type flatten_type; public: typedef node type; }; template struct from_first { private: typedef typename at_index::type first_type; public: typedef node > type; }; template struct create1 { typedef node<_GLIBCXX_TYPELIST_CHAIN1(T1)> type; }; template struct create2 { typedef node<_GLIBCXX_TYPELIST_CHAIN2(T1,T2)> type; }; template struct create3 { typedef node<_GLIBCXX_TYPELIST_CHAIN3(T1,T2,T3)> type; }; template struct create4 { typedef node<_GLIBCXX_TYPELIST_CHAIN4(T1,T2,T3,T4)> type; }; template struct create5 { typedef node<_GLIBCXX_TYPELIST_CHAIN5(T1,T2,T3,T4,T5)> type; }; template struct create6 { typedef node<_GLIBCXX_TYPELIST_CHAIN6(T1,T2,T3,T4,T5,T6)> type; }; } // namespace typelist _GLIBCXX_END_NAMESPACE_VERSION } // namespace #endif PKNd]_8/ext/new_allocator.hnu[// Allocator that wraps operator new -*- C++ -*- // Copyright (C) 2001-2018 Free Software Foundation, Inc. // // This file is part of the GNU ISO C++ Library. This library is free // software; you can redistribute it and/or modify it under the // terms of the GNU General Public License as published by the // Free Software Foundation; either version 3, or (at your option) // any later version. // This library is distributed in the hope that it will be useful, // but WITHOUT ANY WARRANTY; without even the implied warranty of // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the // GNU General Public License for more details. // Under Section 7 of GPL version 3, you are granted additional // permissions described in the GCC Runtime Library Exception, version // 3.1, as published by the Free Software Foundation. // You should have received a copy of the GNU General Public License and // a copy of the GCC Runtime Library Exception along with this program; // see the files COPYING3 and COPYING.RUNTIME respectively. If not, see // . /** @file ext/new_allocator.h * This file is a GNU extension to the Standard C++ Library. */ #ifndef _NEW_ALLOCATOR_H #define _NEW_ALLOCATOR_H 1 #include #include #include #include #if __cplusplus >= 201103L #include #endif namespace __gnu_cxx _GLIBCXX_VISIBILITY(default) { _GLIBCXX_BEGIN_NAMESPACE_VERSION using std::size_t; using std::ptrdiff_t; /** * @brief An allocator that uses global new, as per [20.4]. * @ingroup allocators * * This is precisely the allocator defined in the C++ Standard. * - all allocation calls operator new * - all deallocation calls operator delete * * @tparam _Tp Type of allocated object. */ template class new_allocator { public: typedef size_t size_type; typedef ptrdiff_t difference_type; typedef _Tp* pointer; typedef const _Tp* const_pointer; typedef _Tp& reference; typedef const _Tp& const_reference; typedef _Tp value_type; template struct rebind { typedef new_allocator<_Tp1> other; }; #if __cplusplus >= 201103L // _GLIBCXX_RESOLVE_LIB_DEFECTS // 2103. propagate_on_container_move_assignment typedef std::true_type propagate_on_container_move_assignment; #endif new_allocator() _GLIBCXX_USE_NOEXCEPT { } new_allocator(const new_allocator&) _GLIBCXX_USE_NOEXCEPT { } template new_allocator(const new_allocator<_Tp1>&) _GLIBCXX_USE_NOEXCEPT { } ~new_allocator() _GLIBCXX_USE_NOEXCEPT { } pointer address(reference __x) const _GLIBCXX_NOEXCEPT { return std::__addressof(__x); } const_pointer address(const_reference __x) const _GLIBCXX_NOEXCEPT { return std::__addressof(__x); } // NB: __n is permitted to be 0. The C++ standard says nothing // about what the return value is when __n == 0. pointer allocate(size_type __n, const void* = static_cast(0)) { if (__n > this->max_size()) std::__throw_bad_alloc(); #if __cpp_aligned_new if (alignof(_Tp) > __STDCPP_DEFAULT_NEW_ALIGNMENT__) { std::align_val_t __al = std::align_val_t(alignof(_Tp)); return static_cast<_Tp*>(::operator new(__n * sizeof(_Tp), __al)); } #endif return static_cast<_Tp*>(::operator new(__n * sizeof(_Tp))); } // __p is not permitted to be a null pointer. void deallocate(pointer __p, size_type) { #if __cpp_aligned_new if (alignof(_Tp) > __STDCPP_DEFAULT_NEW_ALIGNMENT__) { ::operator delete(__p, std::align_val_t(alignof(_Tp))); return; } #endif ::operator delete(__p); } size_type max_size() const _GLIBCXX_USE_NOEXCEPT { return size_t(-1) / sizeof(_Tp); } #if __cplusplus >= 201103L template void construct(_Up* __p, _Args&&... __args) { ::new((void *)__p) _Up(std::forward<_Args>(__args)...); } template void destroy(_Up* __p) { __p->~_Up(); } #else // _GLIBCXX_RESOLVE_LIB_DEFECTS // 402. wrong new expression in [some_] allocator::construct void construct(pointer __p, const _Tp& __val) { ::new((void *)__p) _Tp(__val); } void destroy(pointer __p) { __p->~_Tp(); } #endif }; template inline bool operator==(const new_allocator<_Tp>&, const new_allocator<_Tp>&) { return true; } template inline bool operator!=(const new_allocator<_Tp>&, const new_allocator<_Tp>&) { return false; } _GLIBCXX_END_NAMESPACE_VERSION } // namespace #endif PKNd]gss 8/ext/slistnu[// Singly-linked list implementation -*- C++ -*- // Copyright (C) 2001-2018 Free Software Foundation, Inc. // // This file is part of the GNU ISO C++ Library. This library is free // software; you can redistribute it and/or modify it under the // terms of the GNU General Public License as published by the // Free Software Foundation; either version 3, or (at your option) // any later version. // This library is distributed in the hope that it will be useful, // but WITHOUT ANY WARRANTY; without even the implied warranty of // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the // GNU General Public License for more details. // Under Section 7 of GPL version 3, you are granted additional // permissions described in the GCC Runtime Library Exception, version // 3.1, as published by the Free Software Foundation. // You should have received a copy of the GNU General Public License and // a copy of the GCC Runtime Library Exception along with this program; // see the files COPYING3 and COPYING.RUNTIME respectively. If not, see // . /* * Copyright (c) 1997 * Silicon Graphics Computer Systems, Inc. * * Permission to use, copy, modify, distribute and sell this software * and its documentation for any purpose is hereby granted without fee, * provided that the above copyright notice appear in all copies and * that both that copyright notice and this permission notice appear * in supporting documentation. Silicon Graphics makes no * representations about the suitability of this software for any * purpose. It is provided "as is" without express or implied warranty. * */ /** @file ext/slist * This file is a GNU extension to the Standard C++ Library (possibly * containing extensions from the HP/SGI STL subset). */ #ifndef _SLIST #define _SLIST 1 #include #include #include #include #include namespace __gnu_cxx _GLIBCXX_VISIBILITY(default) { _GLIBCXX_BEGIN_NAMESPACE_VERSION using std::size_t; using std::ptrdiff_t; using std::_Construct; using std::_Destroy; using std::allocator; using std::__true_type; using std::__false_type; struct _Slist_node_base { _Slist_node_base* _M_next; }; inline _Slist_node_base* __slist_make_link(_Slist_node_base* __prev_node, _Slist_node_base* __new_node) { __new_node->_M_next = __prev_node->_M_next; __prev_node->_M_next = __new_node; return __new_node; } inline _Slist_node_base* __slist_previous(_Slist_node_base* __head, const _Slist_node_base* __node) { while (__head && __head->_M_next != __node) __head = __head->_M_next; return __head; } inline const _Slist_node_base* __slist_previous(const _Slist_node_base* __head, const _Slist_node_base* __node) { while (__head && __head->_M_next != __node) __head = __head->_M_next; return __head; } inline void __slist_splice_after(_Slist_node_base* __pos, _Slist_node_base* __before_first, _Slist_node_base* __before_last) { if (__pos != __before_first && __pos != __before_last) { _Slist_node_base* __first = __before_first->_M_next; _Slist_node_base* __after = __pos->_M_next; __before_first->_M_next = __before_last->_M_next; __pos->_M_next = __first; __before_last->_M_next = __after; } } inline void __slist_splice_after(_Slist_node_base* __pos, _Slist_node_base* __head) { _Slist_node_base* __before_last = __slist_previous(__head, 0); if (__before_last != __head) { _Slist_node_base* __after = __pos->_M_next; __pos->_M_next = __head->_M_next; __head->_M_next = 0; __before_last->_M_next = __after; } } inline _Slist_node_base* __slist_reverse(_Slist_node_base* __node) { _Slist_node_base* __result = __node; __node = __node->_M_next; __result->_M_next = 0; while(__node) { _Slist_node_base* __next = __node->_M_next; __node->_M_next = __result; __result = __node; __node = __next; } return __result; } inline size_t __slist_size(_Slist_node_base* __node) { size_t __result = 0; for (; __node != 0; __node = __node->_M_next) ++__result; return __result; } template struct _Slist_node : public _Slist_node_base { _Tp _M_data; }; struct _Slist_iterator_base { typedef size_t size_type; typedef ptrdiff_t difference_type; typedef std::forward_iterator_tag iterator_category; _Slist_node_base* _M_node; _Slist_iterator_base(_Slist_node_base* __x) : _M_node(__x) {} void _M_incr() { _M_node = _M_node->_M_next; } bool operator==(const _Slist_iterator_base& __x) const { return _M_node == __x._M_node; } bool operator!=(const _Slist_iterator_base& __x) const { return _M_node != __x._M_node; } }; template struct _Slist_iterator : public _Slist_iterator_base { typedef _Slist_iterator<_Tp, _Tp&, _Tp*> iterator; typedef _Slist_iterator<_Tp, const _Tp&, const _Tp*> const_iterator; typedef _Slist_iterator<_Tp, _Ref, _Ptr> _Self; typedef _Tp value_type; typedef _Ptr pointer; typedef _Ref reference; typedef _Slist_node<_Tp> _Node; explicit _Slist_iterator(_Node* __x) : _Slist_iterator_base(__x) {} _Slist_iterator() : _Slist_iterator_base(0) {} _Slist_iterator(const iterator& __x) : _Slist_iterator_base(__x._M_node) {} reference operator*() const { return ((_Node*) _M_node)->_M_data; } pointer operator->() const { return &(operator*()); } _Self& operator++() { _M_incr(); return *this; } _Self operator++(int) { _Self __tmp = *this; _M_incr(); return __tmp; } }; template struct _Slist_base : public _Alloc::template rebind<_Slist_node<_Tp> >::other { typedef typename _Alloc::template rebind<_Slist_node<_Tp> >::other _Node_alloc; typedef _Alloc allocator_type; allocator_type get_allocator() const { return *static_cast(this); } _Slist_base(const allocator_type& __a) : _Node_alloc(__a) { this->_M_head._M_next = 0; } ~_Slist_base() { _M_erase_after(&this->_M_head, 0); } protected: _Slist_node_base _M_head; _Slist_node<_Tp>* _M_get_node() { return _Node_alloc::allocate(1); } void _M_put_node(_Slist_node<_Tp>* __p) { _Node_alloc::deallocate(__p, 1); } protected: _Slist_node_base* _M_erase_after(_Slist_node_base* __pos) { _Slist_node<_Tp>* __next = (_Slist_node<_Tp>*) (__pos->_M_next); _Slist_node_base* __next_next = __next->_M_next; __pos->_M_next = __next_next; get_allocator().destroy(&__next->_M_data); _M_put_node(__next); return __next_next; } _Slist_node_base* _M_erase_after(_Slist_node_base*, _Slist_node_base*); }; template _Slist_node_base* _Slist_base<_Tp,_Alloc>::_M_erase_after(_Slist_node_base* __before_first, _Slist_node_base* __last_node) { _Slist_node<_Tp>* __cur = (_Slist_node<_Tp>*) (__before_first->_M_next); while (__cur != __last_node) { _Slist_node<_Tp>* __tmp = __cur; __cur = (_Slist_node<_Tp>*) __cur->_M_next; get_allocator().destroy(&__tmp->_M_data); _M_put_node(__tmp); } __before_first->_M_next = __last_node; return __last_node; } /** * This is an SGI extension. * @ingroup SGIextensions * @doctodo */ template > class slist : private _Slist_base<_Tp,_Alloc> { // concept requirements __glibcxx_class_requires(_Tp, _SGIAssignableConcept) private: typedef _Slist_base<_Tp,_Alloc> _Base; public: typedef _Tp value_type; typedef value_type* pointer; typedef const value_type* const_pointer; typedef value_type& reference; typedef const value_type& const_reference; typedef size_t size_type; typedef ptrdiff_t difference_type; typedef _Slist_iterator<_Tp, _Tp&, _Tp*> iterator; typedef _Slist_iterator<_Tp, const _Tp&, const _Tp*> const_iterator; typedef typename _Base::allocator_type allocator_type; allocator_type get_allocator() const { return _Base::get_allocator(); } private: typedef _Slist_node<_Tp> _Node; typedef _Slist_node_base _Node_base; typedef _Slist_iterator_base _Iterator_base; _Node* _M_create_node(const value_type& __x) { _Node* __node = this->_M_get_node(); __try { get_allocator().construct(&__node->_M_data, __x); __node->_M_next = 0; } __catch(...) { this->_M_put_node(__node); __throw_exception_again; } return __node; } _Node* _M_create_node() { _Node* __node = this->_M_get_node(); __try { get_allocator().construct(&__node->_M_data, value_type()); __node->_M_next = 0; } __catch(...) { this->_M_put_node(__node); __throw_exception_again; } return __node; } public: explicit slist(const allocator_type& __a = allocator_type()) : _Base(__a) {} slist(size_type __n, const value_type& __x, const allocator_type& __a = allocator_type()) : _Base(__a) { _M_insert_after_fill(&this->_M_head, __n, __x); } explicit slist(size_type __n) : _Base(allocator_type()) { _M_insert_after_fill(&this->_M_head, __n, value_type()); } // We don't need any dispatching tricks here, because // _M_insert_after_range already does them. template slist(_InputIterator __first, _InputIterator __last, const allocator_type& __a = allocator_type()) : _Base(__a) { _M_insert_after_range(&this->_M_head, __first, __last); } slist(const slist& __x) : _Base(__x.get_allocator()) { _M_insert_after_range(&this->_M_head, __x.begin(), __x.end()); } slist& operator= (const slist& __x); ~slist() {} public: // assign(), a generalized assignment member function. Two // versions: one that takes a count, and one that takes a range. // The range version is a member template, so we dispatch on whether // or not the type is an integer. void assign(size_type __n, const _Tp& __val) { _M_fill_assign(__n, __val); } void _M_fill_assign(size_type __n, const _Tp& __val); template void assign(_InputIterator __first, _InputIterator __last) { typedef typename std::__is_integer<_InputIterator>::__type _Integral; _M_assign_dispatch(__first, __last, _Integral()); } template void _M_assign_dispatch(_Integer __n, _Integer __val, __true_type) { _M_fill_assign((size_type) __n, (_Tp) __val); } template void _M_assign_dispatch(_InputIterator __first, _InputIterator __last, __false_type); public: iterator begin() { return iterator((_Node*)this->_M_head._M_next); } const_iterator begin() const { return const_iterator((_Node*)this->_M_head._M_next);} iterator end() { return iterator(0); } const_iterator end() const { return const_iterator(0); } // Experimental new feature: before_begin() returns a // non-dereferenceable iterator that, when incremented, yields // begin(). This iterator may be used as the argument to // insert_after, erase_after, etc. Note that even for an empty // slist, before_begin() is not the same iterator as end(). It // is always necessary to increment before_begin() at least once to // obtain end(). iterator before_begin() { return iterator((_Node*) &this->_M_head); } const_iterator before_begin() const { return const_iterator((_Node*) &this->_M_head); } size_type size() const { return __slist_size(this->_M_head._M_next); } size_type max_size() const { return size_type(-1); } bool empty() const { return this->_M_head._M_next == 0; } void swap(slist& __x) { std::swap(this->_M_head._M_next, __x._M_head._M_next); } public: reference front() { return ((_Node*) this->_M_head._M_next)->_M_data; } const_reference front() const { return ((_Node*) this->_M_head._M_next)->_M_data; } void push_front(const value_type& __x) { __slist_make_link(&this->_M_head, _M_create_node(__x)); } void push_front() { __slist_make_link(&this->_M_head, _M_create_node()); } void pop_front() { _Node* __node = (_Node*) this->_M_head._M_next; this->_M_head._M_next = __node->_M_next; get_allocator().destroy(&__node->_M_data); this->_M_put_node(__node); } iterator previous(const_iterator __pos) { return iterator((_Node*) __slist_previous(&this->_M_head, __pos._M_node)); } const_iterator previous(const_iterator __pos) const { return const_iterator((_Node*) __slist_previous(&this->_M_head, __pos._M_node)); } private: _Node* _M_insert_after(_Node_base* __pos, const value_type& __x) { return (_Node*) (__slist_make_link(__pos, _M_create_node(__x))); } _Node* _M_insert_after(_Node_base* __pos) { return (_Node*) (__slist_make_link(__pos, _M_create_node())); } void _M_insert_after_fill(_Node_base* __pos, size_type __n, const value_type& __x) { for (size_type __i = 0; __i < __n; ++__i) __pos = __slist_make_link(__pos, _M_create_node(__x)); } // Check whether it's an integral type. If so, it's not an iterator. template void _M_insert_after_range(_Node_base* __pos, _InIterator __first, _InIterator __last) { typedef typename std::__is_integer<_InIterator>::__type _Integral; _M_insert_after_range(__pos, __first, __last, _Integral()); } template void _M_insert_after_range(_Node_base* __pos, _Integer __n, _Integer __x, __true_type) { _M_insert_after_fill(__pos, __n, __x); } template void _M_insert_after_range(_Node_base* __pos, _InIterator __first, _InIterator __last, __false_type) { while (__first != __last) { __pos = __slist_make_link(__pos, _M_create_node(*__first)); ++__first; } } public: iterator insert_after(iterator __pos, const value_type& __x) { return iterator(_M_insert_after(__pos._M_node, __x)); } iterator insert_after(iterator __pos) { return insert_after(__pos, value_type()); } void insert_after(iterator __pos, size_type __n, const value_type& __x) { _M_insert_after_fill(__pos._M_node, __n, __x); } // We don't need any dispatching tricks here, because // _M_insert_after_range already does them. template void insert_after(iterator __pos, _InIterator __first, _InIterator __last) { _M_insert_after_range(__pos._M_node, __first, __last); } iterator insert(iterator __pos, const value_type& __x) { return iterator(_M_insert_after(__slist_previous(&this->_M_head, __pos._M_node), __x)); } iterator insert(iterator __pos) { return iterator(_M_insert_after(__slist_previous(&this->_M_head, __pos._M_node), value_type())); } void insert(iterator __pos, size_type __n, const value_type& __x) { _M_insert_after_fill(__slist_previous(&this->_M_head, __pos._M_node), __n, __x); } // We don't need any dispatching tricks here, because // _M_insert_after_range already does them. template void insert(iterator __pos, _InIterator __first, _InIterator __last) { _M_insert_after_range(__slist_previous(&this->_M_head, __pos._M_node), __first, __last); } public: iterator erase_after(iterator __pos) { return iterator((_Node*) this->_M_erase_after(__pos._M_node)); } iterator erase_after(iterator __before_first, iterator __last) { return iterator((_Node*) this->_M_erase_after(__before_first._M_node, __last._M_node)); } iterator erase(iterator __pos) { return iterator((_Node*) this->_M_erase_after (__slist_previous(&this->_M_head, __pos._M_node))); } iterator erase(iterator __first, iterator __last) { return iterator((_Node*) this->_M_erase_after (__slist_previous(&this->_M_head, __first._M_node), __last._M_node)); } void resize(size_type new_size, const _Tp& __x); void resize(size_type new_size) { resize(new_size, _Tp()); } void clear() { this->_M_erase_after(&this->_M_head, 0); } public: // Moves the range [__before_first + 1, __before_last + 1) to *this, // inserting it immediately after __pos. This is constant time. void splice_after(iterator __pos, iterator __before_first, iterator __before_last) { if (__before_first != __before_last) __slist_splice_after(__pos._M_node, __before_first._M_node, __before_last._M_node); } // Moves the element that follows __prev to *this, inserting it // immediately after __pos. This is constant time. void splice_after(iterator __pos, iterator __prev) { __slist_splice_after(__pos._M_node, __prev._M_node, __prev._M_node->_M_next); } // Removes all of the elements from the list __x to *this, inserting // them immediately after __pos. __x must not be *this. Complexity: // linear in __x.size(). void splice_after(iterator __pos, slist& __x) { __slist_splice_after(__pos._M_node, &__x._M_head); } // Linear in distance(begin(), __pos), and linear in __x.size(). void splice(iterator __pos, slist& __x) { if (__x._M_head._M_next) __slist_splice_after(__slist_previous(&this->_M_head, __pos._M_node), &__x._M_head, __slist_previous(&__x._M_head, 0)); } // Linear in distance(begin(), __pos), and in distance(__x.begin(), __i). void splice(iterator __pos, slist& __x, iterator __i) { __slist_splice_after(__slist_previous(&this->_M_head, __pos._M_node), __slist_previous(&__x._M_head, __i._M_node), __i._M_node); } // Linear in distance(begin(), __pos), in distance(__x.begin(), __first), // and in distance(__first, __last). void splice(iterator __pos, slist& __x, iterator __first, iterator __last) { if (__first != __last) __slist_splice_after(__slist_previous(&this->_M_head, __pos._M_node), __slist_previous(&__x._M_head, __first._M_node), __slist_previous(__first._M_node, __last._M_node)); } public: void reverse() { if (this->_M_head._M_next) this->_M_head._M_next = __slist_reverse(this->_M_head._M_next); } void remove(const _Tp& __val); void unique(); void merge(slist& __x); void sort(); template void remove_if(_Predicate __pred); template void unique(_BinaryPredicate __pred); template void merge(slist&, _StrictWeakOrdering); template void sort(_StrictWeakOrdering __comp); }; template slist<_Tp, _Alloc>& slist<_Tp, _Alloc>::operator=(const slist<_Tp, _Alloc>& __x) { if (&__x != this) { _Node_base* __p1 = &this->_M_head; _Node* __n1 = (_Node*) this->_M_head._M_next; const _Node* __n2 = (const _Node*) __x._M_head._M_next; while (__n1 && __n2) { __n1->_M_data = __n2->_M_data; __p1 = __n1; __n1 = (_Node*) __n1->_M_next; __n2 = (const _Node*) __n2->_M_next; } if (__n2 == 0) this->_M_erase_after(__p1, 0); else _M_insert_after_range(__p1, const_iterator((_Node*)__n2), const_iterator(0)); } return *this; } template void slist<_Tp, _Alloc>::_M_fill_assign(size_type __n, const _Tp& __val) { _Node_base* __prev = &this->_M_head; _Node* __node = (_Node*) this->_M_head._M_next; for (; __node != 0 && __n > 0; --__n) { __node->_M_data = __val; __prev = __node; __node = (_Node*) __node->_M_next; } if (__n > 0) _M_insert_after_fill(__prev, __n, __val); else this->_M_erase_after(__prev, 0); } template template void slist<_Tp, _Alloc>::_M_assign_dispatch(_InputIterator __first, _InputIterator __last, __false_type) { _Node_base* __prev = &this->_M_head; _Node* __node = (_Node*) this->_M_head._M_next; while (__node != 0 && __first != __last) { __node->_M_data = *__first; __prev = __node; __node = (_Node*) __node->_M_next; ++__first; } if (__first != __last) _M_insert_after_range(__prev, __first, __last); else this->_M_erase_after(__prev, 0); } template inline bool operator==(const slist<_Tp, _Alloc>& _SL1, const slist<_Tp, _Alloc>& _SL2) { typedef typename slist<_Tp,_Alloc>::const_iterator const_iterator; const_iterator __end1 = _SL1.end(); const_iterator __end2 = _SL2.end(); const_iterator __i1 = _SL1.begin(); const_iterator __i2 = _SL2.begin(); while (__i1 != __end1 && __i2 != __end2 && *__i1 == *__i2) { ++__i1; ++__i2; } return __i1 == __end1 && __i2 == __end2; } template inline bool operator<(const slist<_Tp, _Alloc>& _SL1, const slist<_Tp, _Alloc>& _SL2) { return std::lexicographical_compare(_SL1.begin(), _SL1.end(), _SL2.begin(), _SL2.end()); } template inline bool operator!=(const slist<_Tp, _Alloc>& _SL1, const slist<_Tp, _Alloc>& _SL2) { return !(_SL1 == _SL2); } template inline bool operator>(const slist<_Tp, _Alloc>& _SL1, const slist<_Tp, _Alloc>& _SL2) { return _SL2 < _SL1; } template inline bool operator<=(const slist<_Tp, _Alloc>& _SL1, const slist<_Tp, _Alloc>& _SL2) { return !(_SL2 < _SL1); } template inline bool operator>=(const slist<_Tp, _Alloc>& _SL1, const slist<_Tp, _Alloc>& _SL2) { return !(_SL1 < _SL2); } template inline void swap(slist<_Tp, _Alloc>& __x, slist<_Tp, _Alloc>& __y) { __x.swap(__y); } template void slist<_Tp, _Alloc>::resize(size_type __len, const _Tp& __x) { _Node_base* __cur = &this->_M_head; while (__cur->_M_next != 0 && __len > 0) { --__len; __cur = __cur->_M_next; } if (__cur->_M_next) this->_M_erase_after(__cur, 0); else _M_insert_after_fill(__cur, __len, __x); } template void slist<_Tp, _Alloc>::remove(const _Tp& __val) { _Node_base* __cur = &this->_M_head; while (__cur && __cur->_M_next) { if (((_Node*) __cur->_M_next)->_M_data == __val) this->_M_erase_after(__cur); else __cur = __cur->_M_next; } } template void slist<_Tp, _Alloc>::unique() { _Node_base* __cur = this->_M_head._M_next; if (__cur) { while (__cur->_M_next) { if (((_Node*)__cur)->_M_data == ((_Node*)(__cur->_M_next))->_M_data) this->_M_erase_after(__cur); else __cur = __cur->_M_next; } } } template void slist<_Tp, _Alloc>::merge(slist<_Tp, _Alloc>& __x) { _Node_base* __n1 = &this->_M_head; while (__n1->_M_next && __x._M_head._M_next) { if (((_Node*) __x._M_head._M_next)->_M_data < ((_Node*) __n1->_M_next)->_M_data) __slist_splice_after(__n1, &__x._M_head, __x._M_head._M_next); __n1 = __n1->_M_next; } if (__x._M_head._M_next) { __n1->_M_next = __x._M_head._M_next; __x._M_head._M_next = 0; } } template void slist<_Tp, _Alloc>::sort() { if (this->_M_head._M_next && this->_M_head._M_next->_M_next) { slist __carry; slist __counter[64]; int __fill = 0; while (!empty()) { __slist_splice_after(&__carry._M_head, &this->_M_head, this->_M_head._M_next); int __i = 0; while (__i < __fill && !__counter[__i].empty()) { __counter[__i].merge(__carry); __carry.swap(__counter[__i]); ++__i; } __carry.swap(__counter[__i]); if (__i == __fill) ++__fill; } for (int __i = 1; __i < __fill; ++__i) __counter[__i].merge(__counter[__i-1]); this->swap(__counter[__fill-1]); } } template template void slist<_Tp, _Alloc>::remove_if(_Predicate __pred) { _Node_base* __cur = &this->_M_head; while (__cur->_M_next) { if (__pred(((_Node*) __cur->_M_next)->_M_data)) this->_M_erase_after(__cur); else __cur = __cur->_M_next; } } template template void slist<_Tp, _Alloc>::unique(_BinaryPredicate __pred) { _Node* __cur = (_Node*) this->_M_head._M_next; if (__cur) { while (__cur->_M_next) { if (__pred(((_Node*)__cur)->_M_data, ((_Node*)(__cur->_M_next))->_M_data)) this->_M_erase_after(__cur); else __cur = (_Node*) __cur->_M_next; } } } template template void slist<_Tp, _Alloc>::merge(slist<_Tp, _Alloc>& __x, _StrictWeakOrdering __comp) { _Node_base* __n1 = &this->_M_head; while (__n1->_M_next && __x._M_head._M_next) { if (__comp(((_Node*) __x._M_head._M_next)->_M_data, ((_Node*) __n1->_M_next)->_M_data)) __slist_splice_after(__n1, &__x._M_head, __x._M_head._M_next); __n1 = __n1->_M_next; } if (__x._M_head._M_next) { __n1->_M_next = __x._M_head._M_next; __x._M_head._M_next = 0; } } template template void slist<_Tp, _Alloc>::sort(_StrictWeakOrdering __comp) { if (this->_M_head._M_next && this->_M_head._M_next->_M_next) { slist __carry; slist __counter[64]; int __fill = 0; while (!empty()) { __slist_splice_after(&__carry._M_head, &this->_M_head, this->_M_head._M_next); int __i = 0; while (__i < __fill && !__counter[__i].empty()) { __counter[__i].merge(__carry, __comp); __carry.swap(__counter[__i]); ++__i; } __carry.swap(__counter[__i]); if (__i == __fill) ++__fill; } for (int __i = 1; __i < __fill; ++__i) __counter[__i].merge(__counter[__i-1], __comp); this->swap(__counter[__fill-1]); } } _GLIBCXX_END_NAMESPACE_VERSION } // namespace namespace std _GLIBCXX_VISIBILITY(default) { _GLIBCXX_BEGIN_NAMESPACE_VERSION // Specialization of insert_iterator so that insertions will be constant // time rather than linear time. template class insert_iterator<__gnu_cxx::slist<_Tp, _Alloc> > { protected: typedef __gnu_cxx::slist<_Tp, _Alloc> _Container; _Container* container; typename _Container::iterator iter; public: typedef _Container container_type; typedef output_iterator_tag iterator_category; typedef void value_type; typedef void difference_type; typedef void pointer; typedef void reference; insert_iterator(_Container& __x, typename _Container::iterator __i) : container(&__x) { if (__i == __x.begin()) iter = __x.before_begin(); else iter = __x.previous(__i); } insert_iterator<_Container>& operator=(const typename _Container::value_type& __value) { iter = container->insert_after(iter, __value); return *this; } insert_iterator<_Container>& operator*() { return *this; } insert_iterator<_Container>& operator++() { return *this; } insert_iterator<_Container>& operator++(int) { return *this; } }; _GLIBCXX_END_NAMESPACE_VERSION } // namespace #endif PKNd]q--8/ext/extptr_allocator.hnu[// -*- C++ -*- // Copyright (C) 2008-2018 Free Software Foundation, Inc. // // This file is part of the GNU ISO C++ Library. This library is free // software; you can redistribute it and/or modify it under the // terms of the GNU General Public License as published by the // Free Software Foundation; either version 3, or (at your option) // any later version. // This library is distributed in the hope that it will be useful, // but WITHOUT ANY WARRANTY; without even the implied warranty of // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the // GNU General Public License for more details. // Under Section 7 of GPL version 3, you are granted additional // permissions described in the GCC Runtime Library Exception, version // 3.1, as published by the Free Software Foundation. // You should have received a copy of the GNU General Public License and // a copy of the GCC Runtime Library Exception along with this program; // see the files COPYING3 and COPYING.RUNTIME respectively. If not, see // . /** * @file ext/extptr_allocator.h * This file is a GNU extension to the Standard C++ Library. * * @author Bob Walters * * An example allocator which uses an alternative pointer type from * bits/pointer.h. Supports test cases which confirm container support * for alternative pointers. */ #ifndef _EXTPTR_ALLOCATOR_H #define _EXTPTR_ALLOCATOR_H 1 #include #include #include namespace __gnu_cxx _GLIBCXX_VISIBILITY(default) { _GLIBCXX_BEGIN_NAMESPACE_VERSION /** * @brief An example allocator which uses a non-standard pointer type. * @ingroup allocators * * This allocator specifies that containers use a 'relative pointer' as it's * pointer type. (See ext/pointer.h) Memory allocation in this example * is still performed using std::allocator. */ template class _ExtPtr_allocator { public: typedef std::size_t size_type; typedef std::ptrdiff_t difference_type; // Note the non-standard pointer types. typedef _Pointer_adapter<_Relative_pointer_impl<_Tp> > pointer; typedef _Pointer_adapter<_Relative_pointer_impl > const_pointer; typedef _Tp& reference; typedef const _Tp& const_reference; typedef _Tp value_type; template struct rebind { typedef _ExtPtr_allocator<_Up> other; }; _ExtPtr_allocator() _GLIBCXX_USE_NOEXCEPT : _M_real_alloc() { } _ExtPtr_allocator(const _ExtPtr_allocator& __rarg) _GLIBCXX_USE_NOEXCEPT : _M_real_alloc(__rarg._M_real_alloc) { } template _ExtPtr_allocator(const _ExtPtr_allocator<_Up>& __rarg) _GLIBCXX_USE_NOEXCEPT : _M_real_alloc(__rarg._M_getUnderlyingImp()) { } ~_ExtPtr_allocator() _GLIBCXX_USE_NOEXCEPT { } pointer address(reference __x) const _GLIBCXX_NOEXCEPT { return std::__addressof(__x); } const_pointer address(const_reference __x) const _GLIBCXX_NOEXCEPT { return std::__addressof(__x); } pointer allocate(size_type __n, void* __hint = 0) { return _M_real_alloc.allocate(__n,__hint); } void deallocate(pointer __p, size_type __n) { _M_real_alloc.deallocate(__p.get(), __n); } size_type max_size() const _GLIBCXX_USE_NOEXCEPT { return __numeric_traits::__max / sizeof(_Tp); } #if __cplusplus >= 201103L template void construct(_Up* __p, _Args&&... __args) { ::new((void *)__p) _Up(std::forward<_Args>(__args)...); } template void construct(pointer __p, _Args&&... __args) { construct(__p.get(), std::forward<_Args>(__args)...); } template void destroy(_Up* __p) { __p->~_Up(); } void destroy(pointer __p) { destroy(__p.get()); } #else void construct(pointer __p, const _Tp& __val) { ::new(__p.get()) _Tp(__val); } void destroy(pointer __p) { __p->~_Tp(); } #endif template inline bool operator==(const _ExtPtr_allocator<_Up>& __rarg) { return _M_real_alloc == __rarg._M_getUnderlyingImp(); } inline bool operator==(const _ExtPtr_allocator& __rarg) { return _M_real_alloc == __rarg._M_real_alloc; } template inline bool operator!=(const _ExtPtr_allocator<_Up>& __rarg) { return _M_real_alloc != __rarg._M_getUnderlyingImp(); } inline bool operator!=(const _ExtPtr_allocator& __rarg) { return _M_real_alloc != __rarg._M_real_alloc; } template inline friend void swap(_ExtPtr_allocator<_Up>&, _ExtPtr_allocator<_Up>&); // A method specific to this implementation. const std::allocator<_Tp>& _M_getUnderlyingImp() const { return _M_real_alloc; } private: std::allocator<_Tp> _M_real_alloc; }; // _ExtPtr_allocator specialization. template<> class _ExtPtr_allocator { public: typedef std::size_t size_type; typedef std::ptrdiff_t difference_type; typedef void value_type; // Note the non-standard pointer types typedef _Pointer_adapter<_Relative_pointer_impl > pointer; typedef _Pointer_adapter<_Relative_pointer_impl > const_pointer; template struct rebind { typedef _ExtPtr_allocator<_Up> other; }; private: std::allocator _M_real_alloc; }; template inline void swap(_ExtPtr_allocator<_Tp>& __larg, _ExtPtr_allocator<_Tp>& __rarg) { std::allocator<_Tp> __tmp( __rarg._M_real_alloc ); __rarg._M_real_alloc = __larg._M_real_alloc; __larg._M_real_alloc = __tmp; } _GLIBCXX_END_NAMESPACE_VERSION } // namespace #endif /* _EXTPTR_ALLOCATOR_H */ PKNd]&v8/ext/pod_char_traits.hnu[// POD character, std::char_traits specialization -*- C++ -*- // Copyright (C) 2002-2018 Free Software Foundation, Inc. // // This file is part of the GNU ISO C++ Library. This library is free // software; you can redistribute it and/or modify it under the // terms of the GNU General Public License as published by the // Free Software Foundation; either version 3, or (at your option) // any later version. // This library is distributed in the hope that it will be useful, // but WITHOUT ANY WARRANTY; without even the implied warranty of // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the // GNU General Public License for more details. // Under Section 7 of GPL version 3, you are granted additional // permissions described in the GCC Runtime Library Exception, version // 3.1, as published by the Free Software Foundation. // You should have received a copy of the GNU General Public License and // a copy of the GCC Runtime Library Exception along with this program; // see the files COPYING3 and COPYING.RUNTIME respectively. If not, see // . /** @file ext/pod_char_traits.h * This file is a GNU extension to the Standard C++ Library. */ // Gabriel Dos Reis // Benjamin Kosnik #ifndef _POD_CHAR_TRAITS_H #define _POD_CHAR_TRAITS_H 1 #pragma GCC system_header #include namespace __gnu_cxx _GLIBCXX_VISIBILITY(default) { _GLIBCXX_BEGIN_NAMESPACE_VERSION // POD character abstraction. // NB: The char_type parameter is a subset of int_type, as to allow // int_type to properly hold the full range of char_type values as // well as EOF. /// @brief A POD class that serves as a character abstraction class. template struct character { typedef _Value value_type; typedef _Int int_type; typedef _St state_type; typedef character<_Value, _Int, _St> char_type; value_type value; template static char_type from(const V2& v) { char_type ret = { static_cast(v) }; return ret; } template static V2 to(const char_type& c) { V2 ret = { static_cast(c.value) }; return ret; } }; template inline bool operator==(const character<_Value, _Int, _St>& lhs, const character<_Value, _Int, _St>& rhs) { return lhs.value == rhs.value; } template inline bool operator<(const character<_Value, _Int, _St>& lhs, const character<_Value, _Int, _St>& rhs) { return lhs.value < rhs.value; } _GLIBCXX_END_NAMESPACE_VERSION } // namespace namespace std _GLIBCXX_VISIBILITY(default) { _GLIBCXX_BEGIN_NAMESPACE_VERSION /// char_traits<__gnu_cxx::character> specialization. template struct char_traits<__gnu_cxx::character<_Value, _Int, _St> > { typedef __gnu_cxx::character<_Value, _Int, _St> char_type; typedef typename char_type::int_type int_type; typedef typename char_type::state_type state_type; typedef fpos pos_type; typedef streamoff off_type; static void assign(char_type& __c1, const char_type& __c2) { __c1 = __c2; } static bool eq(const char_type& __c1, const char_type& __c2) { return __c1 == __c2; } static bool lt(const char_type& __c1, const char_type& __c2) { return __c1 < __c2; } static int compare(const char_type* __s1, const char_type* __s2, size_t __n) { for (size_t __i = 0; __i < __n; ++__i) if (!eq(__s1[__i], __s2[__i])) return lt(__s1[__i], __s2[__i]) ? -1 : 1; return 0; } static size_t length(const char_type* __s) { const char_type* __p = __s; while (__p->value) ++__p; return (__p - __s); } static const char_type* find(const char_type* __s, size_t __n, const char_type& __a) { for (const char_type* __p = __s; size_t(__p - __s) < __n; ++__p) if (*__p == __a) return __p; return 0; } static char_type* move(char_type* __s1, const char_type* __s2, size_t __n) { if (__n == 0) return __s1; return static_cast (__builtin_memmove(__s1, __s2, __n * sizeof(char_type))); } static char_type* copy(char_type* __s1, const char_type* __s2, size_t __n) { if (__n == 0) return __s1; std::copy(__s2, __s2 + __n, __s1); return __s1; } static char_type* assign(char_type* __s, size_t __n, char_type __a) { std::fill_n(__s, __n, __a); return __s; } static char_type to_char_type(const int_type& __i) { return char_type::template from(__i); } static int_type to_int_type(const char_type& __c) { return char_type::template to(__c); } static bool eq_int_type(const int_type& __c1, const int_type& __c2) { return __c1 == __c2; } static int_type eof() { int_type __r = { static_cast::__value, int_type, int>::__type>(-1) }; return __r; } static int_type not_eof(const int_type& __c) { return eq_int_type(__c, eof()) ? int_type() : __c; } }; _GLIBCXX_END_NAMESPACE_VERSION } // namespace #endif PKNd]8/ext/vstring_util.hnu[// Versatile string utility -*- C++ -*- // Copyright (C) 2005-2018 Free Software Foundation, Inc. // // This file is part of the GNU ISO C++ Library. This library is free // software; you can redistribute it and/or modify it under the // terms of the GNU General Public License as published by the // Free Software Foundation; either version 3, or (at your option) // any later version. // This library is distributed in the hope that it will be useful, // but WITHOUT ANY WARRANTY; without even the implied warranty of // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the // GNU General Public License for more details. // Under Section 7 of GPL version 3, you are granted additional // permissions described in the GCC Runtime Library Exception, version // 3.1, as published by the Free Software Foundation. // You should have received a copy of the GNU General Public License and // a copy of the GCC Runtime Library Exception along with this program; // see the files COPYING3 and COPYING.RUNTIME respectively. If not, see // . /** @file ext/vstring_util.h * This is an internal header file, included by other library headers. * Do not attempt to use it directly. @headername{ext/vstring.h} */ #ifndef _VSTRING_UTIL_H #define _VSTRING_UTIL_H 1 #pragma GCC system_header #include #include #include // For less #include #include #include #include #include #include #include namespace __gnu_cxx _GLIBCXX_VISIBILITY(default) { _GLIBCXX_BEGIN_NAMESPACE_VERSION template struct __vstring_utility { typedef typename _Alloc::template rebind<_CharT>::other _CharT_alloc_type; typedef _Traits traits_type; typedef typename _Traits::char_type value_type; typedef typename _CharT_alloc_type::size_type size_type; typedef typename _CharT_alloc_type::difference_type difference_type; typedef typename _CharT_alloc_type::pointer pointer; typedef typename _CharT_alloc_type::const_pointer const_pointer; // For __sso_string. typedef __gnu_cxx:: __normal_iterator > __sso_iterator; typedef __gnu_cxx:: __normal_iterator > __const_sso_iterator; // For __rc_string. typedef __gnu_cxx:: __normal_iterator > __rc_iterator; typedef __gnu_cxx:: __normal_iterator > __const_rc_iterator; // NB: When the allocator is empty, deriving from it saves space // (http://www.cantrip.org/emptyopt.html). template struct _Alloc_hider : public _Alloc1 { _Alloc_hider(_CharT* __ptr) : _Alloc1(), _M_p(__ptr) { } _Alloc_hider(const _Alloc1& __a, _CharT* __ptr) : _Alloc1(__a), _M_p(__ptr) { } _CharT* _M_p; // The actual data. }; // When __n = 1 way faster than the general multichar // traits_type::copy/move/assign. static void _S_copy(_CharT* __d, const _CharT* __s, size_type __n) { if (__n == 1) traits_type::assign(*__d, *__s); else traits_type::copy(__d, __s, __n); } static void _S_move(_CharT* __d, const _CharT* __s, size_type __n) { if (__n == 1) traits_type::assign(*__d, *__s); else traits_type::move(__d, __s, __n); } static void _S_assign(_CharT* __d, size_type __n, _CharT __c) { if (__n == 1) traits_type::assign(*__d, __c); else traits_type::assign(__d, __n, __c); } // _S_copy_chars is a separate template to permit specialization // to optimize for the common case of pointers as iterators. template static void _S_copy_chars(_CharT* __p, _Iterator __k1, _Iterator __k2) { for (; __k1 != __k2; ++__k1, ++__p) traits_type::assign(*__p, *__k1); // These types are off. } static void _S_copy_chars(_CharT* __p, __sso_iterator __k1, __sso_iterator __k2) { _S_copy_chars(__p, __k1.base(), __k2.base()); } static void _S_copy_chars(_CharT* __p, __const_sso_iterator __k1, __const_sso_iterator __k2) { _S_copy_chars(__p, __k1.base(), __k2.base()); } static void _S_copy_chars(_CharT* __p, __rc_iterator __k1, __rc_iterator __k2) { _S_copy_chars(__p, __k1.base(), __k2.base()); } static void _S_copy_chars(_CharT* __p, __const_rc_iterator __k1, __const_rc_iterator __k2) { _S_copy_chars(__p, __k1.base(), __k2.base()); } static void _S_copy_chars(_CharT* __p, _CharT* __k1, _CharT* __k2) { _S_copy(__p, __k1, __k2 - __k1); } static void _S_copy_chars(_CharT* __p, const _CharT* __k1, const _CharT* __k2) { _S_copy(__p, __k1, __k2 - __k1); } static int _S_compare(size_type __n1, size_type __n2) { const difference_type __d = difference_type(__n1 - __n2); if (__d > __numeric_traits_integer::__max) return __numeric_traits_integer::__max; else if (__d < __numeric_traits_integer::__min) return __numeric_traits_integer::__min; else return int(__d); } }; _GLIBCXX_END_NAMESPACE_VERSION } // namespace #endif /* _VSTRING_UTIL_H */ PKNd]  8/ext/memorynu[// Memory extensions -*- C++ -*- // Copyright (C) 2002-2018 Free Software Foundation, Inc. // // This file is part of the GNU ISO C++ Library. This library is free // software; you can redistribute it and/or modify it under the // terms of the GNU General Public License as published by the // Free Software Foundation; either version 3, or (at your option) // any later version. // This library is distributed in the hope that it will be useful, // but WITHOUT ANY WARRANTY; without even the implied warranty of // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the // GNU General Public License for more details. // Under Section 7 of GPL version 3, you are granted additional // permissions described in the GCC Runtime Library Exception, version // 3.1, as published by the Free Software Foundation. // You should have received a copy of the GNU General Public License and // a copy of the GCC Runtime Library Exception along with this program; // see the files COPYING3 and COPYING.RUNTIME respectively. If not, see // . /* * * Copyright (c) 1994 * Hewlett-Packard Company * * Permission to use, copy, modify, distribute and sell this software * and its documentation for any purpose is hereby granted without fee, * provided that the above copyright notice appear in all copies and * that both that copyright notice and this permission notice appear * in supporting documentation. Hewlett-Packard Company makes no * representations about the suitability of this software for any * purpose. It is provided "as is" without express or implied warranty. * * * Copyright (c) 1996 * Silicon Graphics Computer Systems, Inc. * * Permission to use, copy, modify, distribute and sell this software * and its documentation for any purpose is hereby granted without fee, * provided that the above copyright notice appear in all copies and * that both that copyright notice and this permission notice appear * in supporting documentation. Silicon Graphics makes no * representations about the suitability of this software for any * purpose. It is provided "as is" without express or implied warranty. */ /** @file ext/memory * This file is a GNU extension to the Standard C++ Library (possibly * containing extensions from the HP/SGI STL subset). */ #ifndef _EXT_MEMORY #define _EXT_MEMORY 1 #pragma GCC system_header #include #include namespace __gnu_cxx _GLIBCXX_VISIBILITY(default) { _GLIBCXX_BEGIN_NAMESPACE_VERSION using std::ptrdiff_t; using std::pair; using std::__iterator_category; using std::_Temporary_buffer; template pair<_InputIter, _ForwardIter> __uninitialized_copy_n(_InputIter __first, _Size __count, _ForwardIter __result, std::input_iterator_tag) { _ForwardIter __cur = __result; __try { for (; __count > 0 ; --__count, ++__first, ++__cur) std::_Construct(&*__cur, *__first); return pair<_InputIter, _ForwardIter>(__first, __cur); } __catch(...) { std::_Destroy(__result, __cur); __throw_exception_again; } } template inline pair<_RandomAccessIter, _ForwardIter> __uninitialized_copy_n(_RandomAccessIter __first, _Size __count, _ForwardIter __result, std::random_access_iterator_tag) { _RandomAccessIter __last = __first + __count; return (pair<_RandomAccessIter, _ForwardIter> (__last, std::uninitialized_copy(__first, __last, __result))); } template inline pair<_InputIter, _ForwardIter> __uninitialized_copy_n(_InputIter __first, _Size __count, _ForwardIter __result) { return __gnu_cxx::__uninitialized_copy_n(__first, __count, __result, __iterator_category(__first)); } /** * @brief Copies the range [first,last) into result. * @param __first An input iterator. * @param __count Length * @param __result An output iterator. * @return __result + (__first + __count) * @ingroup SGIextensions * * Like copy(), but does not require an initialized output range. */ template inline pair<_InputIter, _ForwardIter> uninitialized_copy_n(_InputIter __first, _Size __count, _ForwardIter __result) { return __gnu_cxx::__uninitialized_copy_n(__first, __count, __result, __iterator_category(__first)); } // An alternative version of uninitialized_copy_n that constructs // and destroys objects with a user-provided allocator. template pair<_InputIter, _ForwardIter> __uninitialized_copy_n_a(_InputIter __first, _Size __count, _ForwardIter __result, _Allocator __alloc) { _ForwardIter __cur = __result; __try { for (; __count > 0 ; --__count, ++__first, ++__cur) __alloc.construct(&*__cur, *__first); return pair<_InputIter, _ForwardIter>(__first, __cur); } __catch(...) { std::_Destroy(__result, __cur, __alloc); __throw_exception_again; } } template inline pair<_InputIter, _ForwardIter> __uninitialized_copy_n_a(_InputIter __first, _Size __count, _ForwardIter __result, std::allocator<_Tp>) { return __gnu_cxx::uninitialized_copy_n(__first, __count, __result); } /** * This class provides similar behavior and semantics of the standard * functions get_temporary_buffer() and return_temporary_buffer(), but * encapsulated in a type vaguely resembling a standard container. * * By default, a temporary_buffer stores space for objects of * whatever type the Iter iterator points to. It is constructed from a * typical [first,last) range, and provides the begin(), end(), size() * functions, as well as requested_size(). For non-trivial types, copies * of *first will be used to initialize the storage. * * @c malloc is used to obtain underlying storage. * * Like get_temporary_buffer(), not all the requested memory may be * available. Ideally, the created buffer will be large enough to hold a * copy of [first,last), but if size() is less than requested_size(), * then this didn't happen. * * @ingroup SGIextensions */ template ::value_type > struct temporary_buffer : public _Temporary_buffer<_ForwardIterator, _Tp> { /// Requests storage large enough to hold a copy of [first,last). temporary_buffer(_ForwardIterator __first, _ForwardIterator __last) : _Temporary_buffer<_ForwardIterator, _Tp>(__first, __last) { } /// Destroys objects and frees storage. ~temporary_buffer() { } }; _GLIBCXX_END_NAMESPACE_VERSION } // namespace #endif PKNd]FF8/ext/alloc_traits.hnu[// Allocator traits -*- C++ -*- // Copyright (C) 2011-2018 Free Software Foundation, Inc. // // This file is part of the GNU ISO C++ Library. This library is free // software; you can redistribute it and/or modify it under the // terms of the GNU General Public License as published by the // Free Software Foundation; either version 3, or (at your option) // any later version. // This library is distributed in the hope that it will be useful, // but WITHOUT ANY WARRANTY; without even the implied warranty of // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the // GNU General Public License for more details. // Under Section 7 of GPL version 3, you are granted additional // permissions described in the GCC Runtime Library Exception, version // 3.1, as published by the Free Software Foundation. // You should have received a copy of the GNU General Public License and // a copy of the GCC Runtime Library Exception along with this program; // see the files COPYING3 and COPYING.RUNTIME respectively. If not, see // . /** @file ext/alloc_traits.h * This file is a GNU extension to the Standard C++ Library. */ #ifndef _EXT_ALLOC_TRAITS_H #define _EXT_ALLOC_TRAITS_H 1 #pragma GCC system_header #if __cplusplus >= 201103L # include # include #else # include // for __alloc_swap #endif namespace __gnu_cxx _GLIBCXX_VISIBILITY(default) { _GLIBCXX_BEGIN_NAMESPACE_VERSION /** * @brief Uniform interface to C++98 and C++11 allocators. * @ingroup allocators */ template struct __alloc_traits #if __cplusplus >= 201103L : std::allocator_traits<_Alloc> #endif { typedef _Alloc allocator_type; #if __cplusplus >= 201103L typedef std::allocator_traits<_Alloc> _Base_type; typedef typename _Base_type::value_type value_type; typedef typename _Base_type::pointer pointer; typedef typename _Base_type::const_pointer const_pointer; typedef typename _Base_type::size_type size_type; typedef typename _Base_type::difference_type difference_type; // C++11 allocators do not define reference or const_reference typedef value_type& reference; typedef const value_type& const_reference; using _Base_type::allocate; using _Base_type::deallocate; using _Base_type::construct; using _Base_type::destroy; using _Base_type::max_size; private: template using __is_custom_pointer = std::__and_, std::__not_>>; public: // overload construct for non-standard pointer types template static typename std::enable_if<__is_custom_pointer<_Ptr>::value>::type construct(_Alloc& __a, _Ptr __p, _Args&&... __args) { _Base_type::construct(__a, std::__to_address(__p), std::forward<_Args>(__args)...); } // overload destroy for non-standard pointer types template static typename std::enable_if<__is_custom_pointer<_Ptr>::value>::type destroy(_Alloc& __a, _Ptr __p) { _Base_type::destroy(__a, std::__to_address(__p)); } static _Alloc _S_select_on_copy(const _Alloc& __a) { return _Base_type::select_on_container_copy_construction(__a); } static void _S_on_swap(_Alloc& __a, _Alloc& __b) { std::__alloc_on_swap(__a, __b); } static constexpr bool _S_propagate_on_copy_assign() { return _Base_type::propagate_on_container_copy_assignment::value; } static constexpr bool _S_propagate_on_move_assign() { return _Base_type::propagate_on_container_move_assignment::value; } static constexpr bool _S_propagate_on_swap() { return _Base_type::propagate_on_container_swap::value; } static constexpr bool _S_always_equal() { return _Base_type::is_always_equal::value; } static constexpr bool _S_nothrow_move() { return _S_propagate_on_move_assign() || _S_always_equal(); } template struct rebind { typedef typename _Base_type::template rebind_alloc<_Tp> other; }; #else typedef typename _Alloc::pointer pointer; typedef typename _Alloc::const_pointer const_pointer; typedef typename _Alloc::value_type value_type; typedef typename _Alloc::reference reference; typedef typename _Alloc::const_reference const_reference; typedef typename _Alloc::size_type size_type; typedef typename _Alloc::difference_type difference_type; static pointer allocate(_Alloc& __a, size_type __n) { return __a.allocate(__n); } static void deallocate(_Alloc& __a, pointer __p, size_type __n) { __a.deallocate(__p, __n); } template static void construct(_Alloc& __a, pointer __p, const _Tp& __arg) { __a.construct(__p, __arg); } static void destroy(_Alloc& __a, pointer __p) { __a.destroy(__p); } static size_type max_size(const _Alloc& __a) { return __a.max_size(); } static const _Alloc& _S_select_on_copy(const _Alloc& __a) { return __a; } static void _S_on_swap(_Alloc& __a, _Alloc& __b) { // _GLIBCXX_RESOLVE_LIB_DEFECTS // 431. Swapping containers with unequal allocators. std::__alloc_swap<_Alloc>::_S_do_it(__a, __b); } template struct rebind { typedef typename _Alloc::template rebind<_Tp>::other other; }; #endif }; _GLIBCXX_END_NAMESPACE_VERSION } // namespace __gnu_cxx #endif PKNd]kS558/ext/ropeimpl.hnu[// SGI's rope class implementation -*- C++ -*- // Copyright (C) 2001-2018 Free Software Foundation, Inc. // // This file is part of the GNU ISO C++ Library. This library is free // software; you can redistribute it and/or modify it under the // terms of the GNU General Public License as published by the // Free Software Foundation; either version 3, or (at your option) // any later version. // This library is distributed in the hope that it will be useful, // but WITHOUT ANY WARRANTY; without even the implied warranty of // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the // GNU General Public License for more details. // Under Section 7 of GPL version 3, you are granted additional // permissions described in the GCC Runtime Library Exception, version // 3.1, as published by the Free Software Foundation. // You should have received a copy of the GNU General Public License and // a copy of the GCC Runtime Library Exception along with this program; // see the files COPYING3 and COPYING.RUNTIME respectively. If not, see // . /* * Copyright (c) 1997 * Silicon Graphics Computer Systems, Inc. * * Permission to use, copy, modify, distribute and sell this software * and its documentation for any purpose is hereby granted without fee, * provided that the above copyright notice appear in all copies and * that both that copyright notice and this permission notice appear * in supporting documentation. Silicon Graphics makes no * representations about the suitability of this software for any * purpose. It is provided "as is" without express or implied warranty. */ /** @file ropeimpl.h * This is an internal header file, included by other library headers. * Do not attempt to use it directly. @headername{ext/rope} */ #include #include #include #include // For copy_n and lexicographical_compare_3way #include // For uninitialized_copy_n #include // For power namespace __gnu_cxx _GLIBCXX_VISIBILITY(default) { _GLIBCXX_BEGIN_NAMESPACE_VERSION using std::size_t; using std::printf; using std::basic_ostream; using std::__throw_length_error; using std::_Destroy; using std::__uninitialized_fill_n_a; // Set buf_start, buf_end, and buf_ptr appropriately, filling tmp_buf // if necessary. Assumes _M_path_end[leaf_index] and leaf_pos are correct. // Results in a valid buf_ptr if the iterator can be legitimately // dereferenced. template void _Rope_iterator_base<_CharT, _Alloc>:: _S_setbuf(_Rope_iterator_base<_CharT, _Alloc>& __x) { const _RopeRep* __leaf = __x._M_path_end[__x._M_leaf_index]; size_t __leaf_pos = __x._M_leaf_pos; size_t __pos = __x._M_current_pos; switch(__leaf->_M_tag) { case __detail::_S_leaf: __x._M_buf_start = ((_Rope_RopeLeaf<_CharT, _Alloc>*)__leaf)->_M_data; __x._M_buf_ptr = __x._M_buf_start + (__pos - __leaf_pos); __x._M_buf_end = __x._M_buf_start + __leaf->_M_size; break; case __detail::_S_function: case __detail::_S_substringfn: { size_t __len = _S_iterator_buf_len; size_t __buf_start_pos = __leaf_pos; size_t __leaf_end = __leaf_pos + __leaf->_M_size; char_producer<_CharT>* __fn = ((_Rope_RopeFunction<_CharT, _Alloc>*)__leaf)->_M_fn; if (__buf_start_pos + __len <= __pos) { __buf_start_pos = __pos - __len / 4; if (__buf_start_pos + __len > __leaf_end) __buf_start_pos = __leaf_end - __len; } if (__buf_start_pos + __len > __leaf_end) __len = __leaf_end - __buf_start_pos; (*__fn)(__buf_start_pos - __leaf_pos, __len, __x._M_tmp_buf); __x._M_buf_ptr = __x._M_tmp_buf + (__pos - __buf_start_pos); __x._M_buf_start = __x._M_tmp_buf; __x._M_buf_end = __x._M_tmp_buf + __len; } break; default: break; } } // Set path and buffer inside a rope iterator. We assume that // pos and root are already set. template void _Rope_iterator_base<_CharT, _Alloc>:: _S_setcache(_Rope_iterator_base<_CharT, _Alloc>& __x) { const _RopeRep* __path[int(__detail::_S_max_rope_depth) + 1]; const _RopeRep* __curr_rope; int __curr_depth = -1; /* index into path */ size_t __curr_start_pos = 0; size_t __pos = __x._M_current_pos; unsigned char __dirns = 0; // Bit vector marking right turns in the path if (__pos >= __x._M_root->_M_size) { __x._M_buf_ptr = 0; return; } __curr_rope = __x._M_root; if (0 != __curr_rope->_M_c_string) { /* Treat the root as a leaf. */ __x._M_buf_start = __curr_rope->_M_c_string; __x._M_buf_end = __curr_rope->_M_c_string + __curr_rope->_M_size; __x._M_buf_ptr = __curr_rope->_M_c_string + __pos; __x._M_path_end[0] = __curr_rope; __x._M_leaf_index = 0; __x._M_leaf_pos = 0; return; } for(;;) { ++__curr_depth; __path[__curr_depth] = __curr_rope; switch(__curr_rope->_M_tag) { case __detail::_S_leaf: case __detail::_S_function: case __detail::_S_substringfn: __x._M_leaf_pos = __curr_start_pos; goto done; case __detail::_S_concat: { _Rope_RopeConcatenation<_CharT, _Alloc>* __c = (_Rope_RopeConcatenation<_CharT, _Alloc>*)__curr_rope; _RopeRep* __left = __c->_M_left; size_t __left_len = __left->_M_size; __dirns <<= 1; if (__pos >= __curr_start_pos + __left_len) { __dirns |= 1; __curr_rope = __c->_M_right; __curr_start_pos += __left_len; } else __curr_rope = __left; } break; } } done: // Copy last section of path into _M_path_end. { int __i = -1; int __j = __curr_depth + 1 - int(_S_path_cache_len); if (__j < 0) __j = 0; while (__j <= __curr_depth) __x._M_path_end[++__i] = __path[__j++]; __x._M_leaf_index = __i; } __x._M_path_directions = __dirns; _S_setbuf(__x); } // Specialized version of the above. Assumes that // the path cache is valid for the previous position. template void _Rope_iterator_base<_CharT, _Alloc>:: _S_setcache_for_incr(_Rope_iterator_base<_CharT, _Alloc>& __x) { int __current_index = __x._M_leaf_index; const _RopeRep* __current_node = __x._M_path_end[__current_index]; size_t __len = __current_node->_M_size; size_t __node_start_pos = __x._M_leaf_pos; unsigned char __dirns = __x._M_path_directions; _Rope_RopeConcatenation<_CharT, _Alloc>* __c; if (__x._M_current_pos - __node_start_pos < __len) { /* More stuff in this leaf, we just didn't cache it. */ _S_setbuf(__x); return; } // node_start_pos is starting position of last_node. while (--__current_index >= 0) { if (!(__dirns & 1) /* Path turned left */) break; __current_node = __x._M_path_end[__current_index]; __c = (_Rope_RopeConcatenation<_CharT, _Alloc>*)__current_node; // Otherwise we were in the right child. Thus we should pop // the concatenation node. __node_start_pos -= __c->_M_left->_M_size; __dirns >>= 1; } if (__current_index < 0) { // We underflowed the cache. Punt. _S_setcache(__x); return; } __current_node = __x._M_path_end[__current_index]; __c = (_Rope_RopeConcatenation<_CharT, _Alloc>*)__current_node; // current_node is a concatenation node. We are positioned on the first // character in its right child. // node_start_pos is starting position of current_node. __node_start_pos += __c->_M_left->_M_size; __current_node = __c->_M_right; __x._M_path_end[++__current_index] = __current_node; __dirns |= 1; while (__detail::_S_concat == __current_node->_M_tag) { ++__current_index; if (int(_S_path_cache_len) == __current_index) { int __i; for (__i = 0; __i < int(_S_path_cache_len) - 1; __i++) __x._M_path_end[__i] = __x._M_path_end[__i+1]; --__current_index; } __current_node = ((_Rope_RopeConcatenation<_CharT, _Alloc>*)__current_node)->_M_left; __x._M_path_end[__current_index] = __current_node; __dirns <<= 1; // node_start_pos is unchanged. } __x._M_leaf_index = __current_index; __x._M_leaf_pos = __node_start_pos; __x._M_path_directions = __dirns; _S_setbuf(__x); } template void _Rope_iterator_base<_CharT, _Alloc>:: _M_incr(size_t __n) { _M_current_pos += __n; if (0 != _M_buf_ptr) { size_t __chars_left = _M_buf_end - _M_buf_ptr; if (__chars_left > __n) _M_buf_ptr += __n; else if (__chars_left == __n) { _M_buf_ptr += __n; _S_setcache_for_incr(*this); } else _M_buf_ptr = 0; } } template void _Rope_iterator_base<_CharT, _Alloc>:: _M_decr(size_t __n) { if (0 != _M_buf_ptr) { size_t __chars_left = _M_buf_ptr - _M_buf_start; if (__chars_left >= __n) _M_buf_ptr -= __n; else _M_buf_ptr = 0; } _M_current_pos -= __n; } template void _Rope_iterator<_CharT, _Alloc>:: _M_check() { if (_M_root_rope->_M_tree_ptr != this->_M_root) { // _Rope was modified. Get things fixed up. _RopeRep::_S_unref(this->_M_root); this->_M_root = _M_root_rope->_M_tree_ptr; _RopeRep::_S_ref(this->_M_root); this->_M_buf_ptr = 0; } } template inline _Rope_const_iterator<_CharT, _Alloc>:: _Rope_const_iterator(const _Rope_iterator<_CharT, _Alloc>& __x) : _Rope_iterator_base<_CharT, _Alloc>(__x) { } template inline _Rope_iterator<_CharT, _Alloc>:: _Rope_iterator(rope<_CharT, _Alloc>& __r, size_t __pos) : _Rope_iterator_base<_CharT,_Alloc>(__r._M_tree_ptr, __pos), _M_root_rope(&__r) { _RopeRep::_S_ref(this->_M_root); } template inline size_t rope<_CharT, _Alloc>:: _S_char_ptr_len(const _CharT* __s) { const _CharT* __p = __s; while (!_S_is0(*__p)) ++__p; return (__p - __s); } #ifndef __GC template inline void _Rope_RopeRep<_CharT, _Alloc>:: _M_free_c_string() { _CharT* __cstr = _M_c_string; if (0 != __cstr) { size_t __size = this->_M_size + 1; _Destroy(__cstr, __cstr + __size, _M_get_allocator()); this->_Data_deallocate(__cstr, __size); } } template inline void _Rope_RopeRep<_CharT, _Alloc>:: _S_free_string(_CharT* __s, size_t __n, allocator_type& __a) { if (!_S_is_basic_char_type((_CharT*)0)) _Destroy(__s, __s + __n, __a); // This has to be a static member, so this gets a bit messy __a.deallocate(__s, _Rope_RopeLeaf<_CharT, _Alloc>::_S_rounded_up_size(__n)); } // There are several reasons for not doing this with virtual destructors // and a class specific delete operator: // - A class specific delete operator can't easily get access to // allocator instances if we need them. // - Any virtual function would need a 4 or byte vtable pointer; // this only requires a one byte tag per object. template void _Rope_RopeRep<_CharT, _Alloc>:: _M_free_tree() { switch(_M_tag) { case __detail::_S_leaf: { _Rope_RopeLeaf<_CharT, _Alloc>* __l = (_Rope_RopeLeaf<_CharT, _Alloc>*)this; __l->_Rope_RopeLeaf<_CharT, _Alloc>::~_Rope_RopeLeaf(); this->_L_deallocate(__l, 1); break; } case __detail::_S_concat: { _Rope_RopeConcatenation<_CharT,_Alloc>* __c = (_Rope_RopeConcatenation<_CharT, _Alloc>*)this; __c->_Rope_RopeConcatenation<_CharT, _Alloc>:: ~_Rope_RopeConcatenation(); this->_C_deallocate(__c, 1); break; } case __detail::_S_function: { _Rope_RopeFunction<_CharT, _Alloc>* __f = (_Rope_RopeFunction<_CharT, _Alloc>*)this; __f->_Rope_RopeFunction<_CharT, _Alloc>::~_Rope_RopeFunction(); this->_F_deallocate(__f, 1); break; } case __detail::_S_substringfn: { _Rope_RopeSubstring<_CharT, _Alloc>* __ss = (_Rope_RopeSubstring<_CharT, _Alloc>*)this; __ss->_Rope_RopeSubstring<_CharT, _Alloc>:: ~_Rope_RopeSubstring(); this->_S_deallocate(__ss, 1); break; } } } #else template inline void _Rope_RopeRep<_CharT, _Alloc>:: _S_free_string(const _CharT*, size_t, allocator_type) { } #endif // Concatenate a C string onto a leaf rope by copying the rope data. // Used for short ropes. template typename rope<_CharT, _Alloc>::_RopeLeaf* rope<_CharT, _Alloc>:: _S_leaf_concat_char_iter(_RopeLeaf* __r, const _CharT* __iter, size_t __len) { size_t __old_len = __r->_M_size; _CharT* __new_data = (_CharT*) rope::_Data_allocate(_S_rounded_up_size(__old_len + __len)); _RopeLeaf* __result; uninitialized_copy_n(__r->_M_data, __old_len, __new_data); uninitialized_copy_n(__iter, __len, __new_data + __old_len); _S_cond_store_eos(__new_data[__old_len + __len]); __try { __result = _S_new_RopeLeaf(__new_data, __old_len + __len, __r->_M_get_allocator()); } __catch(...) { _RopeRep::__STL_FREE_STRING(__new_data, __old_len + __len, __r->_M_get_allocator()); __throw_exception_again; } return __result; } #ifndef __GC // As above, but it's OK to clobber original if refcount is 1 template typename rope<_CharT,_Alloc>::_RopeLeaf* rope<_CharT, _Alloc>:: _S_destr_leaf_concat_char_iter(_RopeLeaf* __r, const _CharT* __iter, size_t __len) { if (__r->_M_ref_count > 1) return _S_leaf_concat_char_iter(__r, __iter, __len); size_t __old_len = __r->_M_size; if (_S_allocated_capacity(__old_len) >= __old_len + __len) { // The space has been partially initialized for the standard // character types. But that doesn't matter for those types. uninitialized_copy_n(__iter, __len, __r->_M_data + __old_len); if (_S_is_basic_char_type((_CharT*)0)) _S_cond_store_eos(__r->_M_data[__old_len + __len]); else if (__r->_M_c_string != __r->_M_data && 0 != __r->_M_c_string) { __r->_M_free_c_string(); __r->_M_c_string = 0; } __r->_M_size = __old_len + __len; __r->_M_ref_count = 2; return __r; } else { _RopeLeaf* __result = _S_leaf_concat_char_iter(__r, __iter, __len); return __result; } } #endif // Assumes left and right are not 0. // Does not increment (nor decrement on exception) child reference counts. // Result has ref count 1. template typename rope<_CharT, _Alloc>::_RopeRep* rope<_CharT, _Alloc>:: _S_tree_concat(_RopeRep* __left, _RopeRep* __right) { _RopeConcatenation* __result = _S_new_RopeConcatenation(__left, __right, __left-> _M_get_allocator()); size_t __depth = __result->_M_depth; if (__depth > 20 && (__result->_M_size < 1000 || __depth > size_t(__detail::_S_max_rope_depth))) { _RopeRep* __balanced; __try { __balanced = _S_balance(__result); __result->_M_unref_nonnil(); } __catch(...) { rope::_C_deallocate(__result,1); __throw_exception_again; } // In case of exception, we need to deallocate // otherwise dangling result node. But caller // still owns its children. Thus unref is // inappropriate. return __balanced; } else return __result; } template typename rope<_CharT, _Alloc>::_RopeRep* rope<_CharT, _Alloc>:: _S_concat_char_iter(_RopeRep* __r, const _CharT*__s, size_t __slen) { _RopeRep* __result; if (0 == __slen) { _S_ref(__r); return __r; } if (0 == __r) return __STL_ROPE_FROM_UNOWNED_CHAR_PTR(__s, __slen, __r->_M_get_allocator()); if (__r->_M_tag == __detail::_S_leaf && __r->_M_size + __slen <= size_t(_S_copy_max)) { __result = _S_leaf_concat_char_iter((_RopeLeaf*)__r, __s, __slen); return __result; } if (__detail::_S_concat == __r->_M_tag && __detail::_S_leaf == ((_RopeConcatenation*) __r)->_M_right->_M_tag) { _RopeLeaf* __right = (_RopeLeaf* )(((_RopeConcatenation* )__r)->_M_right); if (__right->_M_size + __slen <= size_t(_S_copy_max)) { _RopeRep* __left = ((_RopeConcatenation*)__r)->_M_left; _RopeRep* __nright = _S_leaf_concat_char_iter((_RopeLeaf*)__right, __s, __slen); __left->_M_ref_nonnil(); __try { __result = _S_tree_concat(__left, __nright); } __catch(...) { _S_unref(__left); _S_unref(__nright); __throw_exception_again; } return __result; } } _RopeRep* __nright = __STL_ROPE_FROM_UNOWNED_CHAR_PTR(__s, __slen, __r->_M_get_allocator()); __try { __r->_M_ref_nonnil(); __result = _S_tree_concat(__r, __nright); } __catch(...) { _S_unref(__r); _S_unref(__nright); __throw_exception_again; } return __result; } #ifndef __GC template typename rope<_CharT,_Alloc>::_RopeRep* rope<_CharT,_Alloc>:: _S_destr_concat_char_iter(_RopeRep* __r, const _CharT* __s, size_t __slen) { _RopeRep* __result; if (0 == __r) return __STL_ROPE_FROM_UNOWNED_CHAR_PTR(__s, __slen, __r->_M_get_allocator()); size_t __count = __r->_M_ref_count; size_t __orig_size = __r->_M_size; if (__count > 1) return _S_concat_char_iter(__r, __s, __slen); if (0 == __slen) { __r->_M_ref_count = 2; // One more than before return __r; } if (__orig_size + __slen <= size_t(_S_copy_max) && __detail::_S_leaf == __r->_M_tag) { __result = _S_destr_leaf_concat_char_iter((_RopeLeaf*)__r, __s, __slen); return __result; } if (__detail::_S_concat == __r->_M_tag) { _RopeLeaf* __right = (_RopeLeaf*)(((_RopeConcatenation*) __r)->_M_right); if (__detail::_S_leaf == __right->_M_tag && __right->_M_size + __slen <= size_t(_S_copy_max)) { _RopeRep* __new_right = _S_destr_leaf_concat_char_iter(__right, __s, __slen); if (__right == __new_right) __new_right->_M_ref_count = 1; else __right->_M_unref_nonnil(); __r->_M_ref_count = 2; // One more than before. ((_RopeConcatenation*)__r)->_M_right = __new_right; __r->_M_size = __orig_size + __slen; if (0 != __r->_M_c_string) { __r->_M_free_c_string(); __r->_M_c_string = 0; } return __r; } } _RopeRep* __right = __STL_ROPE_FROM_UNOWNED_CHAR_PTR(__s, __slen, __r->_M_get_allocator()); __r->_M_ref_nonnil(); __try { __result = _S_tree_concat(__r, __right); } __catch(...) { _S_unref(__r); _S_unref(__right); __throw_exception_again; } return __result; } #endif /* !__GC */ template typename rope<_CharT, _Alloc>::_RopeRep* rope<_CharT, _Alloc>:: _S_concat(_RopeRep* __left, _RopeRep* __right) { if (0 == __left) { _S_ref(__right); return __right; } if (0 == __right) { __left->_M_ref_nonnil(); return __left; } if (__detail::_S_leaf == __right->_M_tag) { if (__detail::_S_leaf == __left->_M_tag) { if (__right->_M_size + __left->_M_size <= size_t(_S_copy_max)) return _S_leaf_concat_char_iter((_RopeLeaf*)__left, ((_RopeLeaf*)__right)->_M_data, __right->_M_size); } else if (__detail::_S_concat == __left->_M_tag && __detail::_S_leaf == ((_RopeConcatenation*) __left)->_M_right->_M_tag) { _RopeLeaf* __leftright = (_RopeLeaf*)(((_RopeConcatenation*)__left)->_M_right); if (__leftright->_M_size + __right->_M_size <= size_t(_S_copy_max)) { _RopeRep* __leftleft = ((_RopeConcatenation*)__left)->_M_left; _RopeRep* __rest = _S_leaf_concat_char_iter(__leftright, ((_RopeLeaf*) __right)-> _M_data, __right->_M_size); __leftleft->_M_ref_nonnil(); __try { return(_S_tree_concat(__leftleft, __rest)); } __catch(...) { _S_unref(__leftleft); _S_unref(__rest); __throw_exception_again; } } } } __left->_M_ref_nonnil(); __right->_M_ref_nonnil(); __try { return(_S_tree_concat(__left, __right)); } __catch(...) { _S_unref(__left); _S_unref(__right); __throw_exception_again; } } template typename rope<_CharT, _Alloc>::_RopeRep* rope<_CharT, _Alloc>:: _S_substring(_RopeRep* __base, size_t __start, size_t __endp1) { if (0 == __base) return 0; size_t __len = __base->_M_size; size_t __adj_endp1; const size_t __lazy_threshold = 128; if (__endp1 >= __len) { if (0 == __start) { __base->_M_ref_nonnil(); return __base; } else __adj_endp1 = __len; } else __adj_endp1 = __endp1; switch(__base->_M_tag) { case __detail::_S_concat: { _RopeConcatenation* __c = (_RopeConcatenation*)__base; _RopeRep* __left = __c->_M_left; _RopeRep* __right = __c->_M_right; size_t __left_len = __left->_M_size; _RopeRep* __result; if (__adj_endp1 <= __left_len) return _S_substring(__left, __start, __endp1); else if (__start >= __left_len) return _S_substring(__right, __start - __left_len, __adj_endp1 - __left_len); _Self_destruct_ptr __left_result(_S_substring(__left, __start, __left_len)); _Self_destruct_ptr __right_result(_S_substring(__right, 0, __endp1 - __left_len)); __result = _S_concat(__left_result, __right_result); return __result; } case __detail::_S_leaf: { _RopeLeaf* __l = (_RopeLeaf*)__base; _RopeLeaf* __result; size_t __result_len; if (__start >= __adj_endp1) return 0; __result_len = __adj_endp1 - __start; if (__result_len > __lazy_threshold) goto lazy; #ifdef __GC const _CharT* __section = __l->_M_data + __start; __result = _S_new_RopeLeaf(__section, __result_len, __base->_M_get_allocator()); __result->_M_c_string = 0; // Not eos terminated. #else // We should sometimes create substring node instead. __result = __STL_ROPE_FROM_UNOWNED_CHAR_PTR(__l->_M_data + __start, __result_len, __base-> _M_get_allocator()); #endif return __result; } case __detail::_S_substringfn: // Avoid introducing multiple layers of substring nodes. { _RopeSubstring* __old = (_RopeSubstring*)__base; size_t __result_len; if (__start >= __adj_endp1) return 0; __result_len = __adj_endp1 - __start; if (__result_len > __lazy_threshold) { _RopeSubstring* __result = _S_new_RopeSubstring(__old->_M_base, __start + __old->_M_start, __adj_endp1 - __start, __base->_M_get_allocator()); return __result; } // *** else fall through: *** } case __detail::_S_function: { _RopeFunction* __f = (_RopeFunction*)__base; _CharT* __section; size_t __result_len; if (__start >= __adj_endp1) return 0; __result_len = __adj_endp1 - __start; if (__result_len > __lazy_threshold) goto lazy; __section = (_CharT*) rope::_Data_allocate(_S_rounded_up_size(__result_len)); __try { (*(__f->_M_fn))(__start, __result_len, __section); } __catch(...) { _RopeRep::__STL_FREE_STRING(__section, __result_len, __base->_M_get_allocator()); __throw_exception_again; } _S_cond_store_eos(__section[__result_len]); return _S_new_RopeLeaf(__section, __result_len, __base->_M_get_allocator()); } } lazy: { // Create substring node. return _S_new_RopeSubstring(__base, __start, __adj_endp1 - __start, __base->_M_get_allocator()); } } template class _Rope_flatten_char_consumer : public _Rope_char_consumer<_CharT> { private: _CharT* _M_buf_ptr; public: _Rope_flatten_char_consumer(_CharT* __buffer) { _M_buf_ptr = __buffer; } ~_Rope_flatten_char_consumer() {} bool operator()(const _CharT* __leaf, size_t __n) { uninitialized_copy_n(__leaf, __n, _M_buf_ptr); _M_buf_ptr += __n; return true; } }; template class _Rope_find_char_char_consumer : public _Rope_char_consumer<_CharT> { private: _CharT _M_pattern; public: size_t _M_count; // Number of nonmatching characters _Rope_find_char_char_consumer(_CharT __p) : _M_pattern(__p), _M_count(0) {} ~_Rope_find_char_char_consumer() {} bool operator()(const _CharT* __leaf, size_t __n) { size_t __i; for (__i = 0; __i < __n; __i++) { if (__leaf[__i] == _M_pattern) { _M_count += __i; return false; } } _M_count += __n; return true; } }; template // Here _CharT is both the stream and rope character type. class _Rope_insert_char_consumer : public _Rope_char_consumer<_CharT> { private: typedef basic_ostream<_CharT,_Traits> _Insert_ostream; _Insert_ostream& _M_o; public: _Rope_insert_char_consumer(_Insert_ostream& __writer) : _M_o(__writer) {} ~_Rope_insert_char_consumer() { } // Caller is presumed to own the ostream bool operator() (const _CharT* __leaf, size_t __n); // Returns true to continue traversal. }; template bool _Rope_insert_char_consumer<_CharT, _Traits>:: operator()(const _CharT* __leaf, size_t __n) { size_t __i; // We assume that formatting is set up correctly for each element. for (__i = 0; __i < __n; __i++) _M_o.put(__leaf[__i]); return true; } template bool rope<_CharT, _Alloc>:: _S_apply_to_pieces(_Rope_char_consumer<_CharT>& __c, const _RopeRep* __r, size_t __begin, size_t __end) { if (0 == __r) return true; switch(__r->_M_tag) { case __detail::_S_concat: { _RopeConcatenation* __conc = (_RopeConcatenation*)__r; _RopeRep* __left = __conc->_M_left; size_t __left_len = __left->_M_size; if (__begin < __left_len) { size_t __left_end = std::min(__left_len, __end); if (!_S_apply_to_pieces(__c, __left, __begin, __left_end)) return false; } if (__end > __left_len) { _RopeRep* __right = __conc->_M_right; size_t __right_start = std::max(__left_len, __begin); if (!_S_apply_to_pieces(__c, __right, __right_start - __left_len, __end - __left_len)) return false; } } return true; case __detail::_S_leaf: { _RopeLeaf* __l = (_RopeLeaf*)__r; return __c(__l->_M_data + __begin, __end - __begin); } case __detail::_S_function: case __detail::_S_substringfn: { _RopeFunction* __f = (_RopeFunction*)__r; size_t __len = __end - __begin; bool __result; _CharT* __buffer = (_CharT*)_Alloc().allocate(__len * sizeof(_CharT)); __try { (*(__f->_M_fn))(__begin, __len, __buffer); __result = __c(__buffer, __len); _Alloc().deallocate(__buffer, __len * sizeof(_CharT)); } __catch(...) { _Alloc().deallocate(__buffer, __len * sizeof(_CharT)); __throw_exception_again; } return __result; } default: return false; } } template inline void _Rope_fill(basic_ostream<_CharT, _Traits>& __o, size_t __n) { char __f = __o.fill(); size_t __i; for (__i = 0; __i < __n; __i++) __o.put(__f); } template inline bool _Rope_is_simple(_CharT*) { return false; } inline bool _Rope_is_simple(char*) { return true; } inline bool _Rope_is_simple(wchar_t*) { return true; } template basic_ostream<_CharT, _Traits>& operator<<(basic_ostream<_CharT, _Traits>& __o, const rope<_CharT, _Alloc>& __r) { size_t __w = __o.width(); bool __left = bool(__o.flags() & std::ios::left); size_t __pad_len; size_t __rope_len = __r.size(); _Rope_insert_char_consumer<_CharT, _Traits> __c(__o); bool __is_simple = _Rope_is_simple((_CharT*)0); if (__rope_len < __w) __pad_len = __w - __rope_len; else __pad_len = 0; if (!__is_simple) __o.width(__w / __rope_len); __try { if (__is_simple && !__left && __pad_len > 0) _Rope_fill(__o, __pad_len); __r.apply_to_pieces(0, __r.size(), __c); if (__is_simple && __left && __pad_len > 0) _Rope_fill(__o, __pad_len); if (!__is_simple) __o.width(__w); } __catch(...) { if (!__is_simple) __o.width(__w); __throw_exception_again; } return __o; } template _CharT* rope<_CharT, _Alloc>:: _S_flatten(_RopeRep* __r, size_t __start, size_t __len, _CharT* __buffer) { _Rope_flatten_char_consumer<_CharT> __c(__buffer); _S_apply_to_pieces(__c, __r, __start, __start + __len); return(__buffer + __len); } template size_t rope<_CharT, _Alloc>:: find(_CharT __pattern, size_t __start) const { _Rope_find_char_char_consumer<_CharT> __c(__pattern); _S_apply_to_pieces(__c, this->_M_tree_ptr, __start, size()); size_type __result_pos = __start + __c._M_count; #ifndef __STL_OLD_ROPE_SEMANTICS if (__result_pos == size()) __result_pos = npos; #endif return __result_pos; } template _CharT* rope<_CharT, _Alloc>:: _S_flatten(_RopeRep* __r, _CharT* __buffer) { if (0 == __r) return __buffer; switch(__r->_M_tag) { case __detail::_S_concat: { _RopeConcatenation* __c = (_RopeConcatenation*)__r; _RopeRep* __left = __c->_M_left; _RopeRep* __right = __c->_M_right; _CharT* __rest = _S_flatten(__left, __buffer); return _S_flatten(__right, __rest); } case __detail::_S_leaf: { _RopeLeaf* __l = (_RopeLeaf*)__r; return copy_n(__l->_M_data, __l->_M_size, __buffer).second; } case __detail::_S_function: case __detail::_S_substringfn: // We don't yet do anything with substring nodes. // This needs to be fixed before ropefiles will work well. { _RopeFunction* __f = (_RopeFunction*)__r; (*(__f->_M_fn))(0, __f->_M_size, __buffer); return __buffer + __f->_M_size; } default: return 0; } } // This needs work for _CharT != char template void rope<_CharT, _Alloc>:: _S_dump(_RopeRep* __r, int __indent) { for (int __i = 0; __i < __indent; __i++) putchar(' '); if (0 == __r) { printf("NULL\n"); return; } if (__detail::_S_concat == __r->_M_tag) { _RopeConcatenation* __c = (_RopeConcatenation*)__r; _RopeRep* __left = __c->_M_left; _RopeRep* __right = __c->_M_right; #ifdef __GC printf("Concatenation %p (depth = %d, len = %ld, %s balanced)\n", __r, __r->_M_depth, __r->_M_size, __r->_M_is_balanced? "" : "not"); #else printf("Concatenation %p (rc = %ld, depth = %d, " "len = %ld, %s balanced)\n", __r, __r->_M_ref_count, __r->_M_depth, __r->_M_size, __r->_M_is_balanced? "" : "not"); #endif _S_dump(__left, __indent + 2); _S_dump(__right, __indent + 2); return; } else { const char* __kind; switch (__r->_M_tag) { case __detail::_S_leaf: __kind = "Leaf"; break; case __detail::_S_function: __kind = "Function"; break; case __detail::_S_substringfn: __kind = "Function representing substring"; break; default: __kind = "(corrupted kind field!)"; } #ifdef __GC printf("%s %p (depth = %d, len = %ld) ", __kind, __r, __r->_M_depth, __r->_M_size); #else printf("%s %p (rc = %ld, depth = %d, len = %ld) ", __kind, __r, __r->_M_ref_count, __r->_M_depth, __r->_M_size); #endif if (_S_is_one_byte_char_type((_CharT*)0)) { const int __max_len = 40; _Self_destruct_ptr __prefix(_S_substring(__r, 0, __max_len)); _CharT __buffer[__max_len + 1]; bool __too_big = __r->_M_size > __prefix->_M_size; _S_flatten(__prefix, __buffer); __buffer[__prefix->_M_size] = _S_eos((_CharT*)0); printf("%s%s\n", (char*)__buffer, __too_big? "...\n" : "\n"); } else printf("\n"); } } template const unsigned long rope<_CharT, _Alloc>:: _S_min_len[int(__detail::_S_max_rope_depth) + 1] = { /* 0 */1, /* 1 */2, /* 2 */3, /* 3 */5, /* 4 */8, /* 5 */13, /* 6 */21, /* 7 */34, /* 8 */55, /* 9 */89, /* 10 */144, /* 11 */233, /* 12 */377, /* 13 */610, /* 14 */987, /* 15 */1597, /* 16 */2584, /* 17 */4181, /* 18 */6765, /* 19 */10946, /* 20 */17711, /* 21 */28657, /* 22 */46368, /* 23 */75025, /* 24 */121393, /* 25 */196418, /* 26 */317811, /* 27 */514229, /* 28 */832040, /* 29 */1346269, /* 30 */2178309, /* 31 */3524578, /* 32 */5702887, /* 33 */9227465, /* 34 */14930352, /* 35 */24157817, /* 36 */39088169, /* 37 */63245986, /* 38 */102334155, /* 39 */165580141, /* 40 */267914296, /* 41 */433494437, /* 42 */701408733, /* 43 */1134903170, /* 44 */1836311903, /* 45 */2971215073u }; // These are Fibonacci numbers < 2**32. template typename rope<_CharT, _Alloc>::_RopeRep* rope<_CharT, _Alloc>:: _S_balance(_RopeRep* __r) { _RopeRep* __forest[int(__detail::_S_max_rope_depth) + 1]; _RopeRep* __result = 0; int __i; // Invariant: // The concatenation of forest in descending order is equal to __r. // __forest[__i]._M_size >= _S_min_len[__i] // __forest[__i]._M_depth = __i // References from forest are included in refcount. for (__i = 0; __i <= int(__detail::_S_max_rope_depth); ++__i) __forest[__i] = 0; __try { _S_add_to_forest(__r, __forest); for (__i = 0; __i <= int(__detail::_S_max_rope_depth); ++__i) if (0 != __forest[__i]) { #ifndef __GC _Self_destruct_ptr __old(__result); #endif __result = _S_concat(__forest[__i], __result); __forest[__i]->_M_unref_nonnil(); #if !defined(__GC) && __cpp_exceptions __forest[__i] = 0; #endif } } __catch(...) { for(__i = 0; __i <= int(__detail::_S_max_rope_depth); __i++) _S_unref(__forest[__i]); __throw_exception_again; } if (__result->_M_depth > int(__detail::_S_max_rope_depth)) __throw_length_error(__N("rope::_S_balance")); return(__result); } template void rope<_CharT, _Alloc>:: _S_add_to_forest(_RopeRep* __r, _RopeRep** __forest) { if (__r->_M_is_balanced) { _S_add_leaf_to_forest(__r, __forest); return; } { _RopeConcatenation* __c = (_RopeConcatenation*)__r; _S_add_to_forest(__c->_M_left, __forest); _S_add_to_forest(__c->_M_right, __forest); } } template void rope<_CharT, _Alloc>:: _S_add_leaf_to_forest(_RopeRep* __r, _RopeRep** __forest) { _RopeRep* __insertee; // included in refcount _RopeRep* __too_tiny = 0; // included in refcount int __i; // forest[0..__i-1] is empty size_t __s = __r->_M_size; for (__i = 0; __s >= _S_min_len[__i+1]/* not this bucket */; ++__i) { if (0 != __forest[__i]) { #ifndef __GC _Self_destruct_ptr __old(__too_tiny); #endif __too_tiny = _S_concat_and_set_balanced(__forest[__i], __too_tiny); __forest[__i]->_M_unref_nonnil(); __forest[__i] = 0; } } { #ifndef __GC _Self_destruct_ptr __old(__too_tiny); #endif __insertee = _S_concat_and_set_balanced(__too_tiny, __r); } // Too_tiny dead, and no longer included in refcount. // Insertee is live and included. for (;; ++__i) { if (0 != __forest[__i]) { #ifndef __GC _Self_destruct_ptr __old(__insertee); #endif __insertee = _S_concat_and_set_balanced(__forest[__i], __insertee); __forest[__i]->_M_unref_nonnil(); __forest[__i] = 0; } if (__i == int(__detail::_S_max_rope_depth) || __insertee->_M_size < _S_min_len[__i+1]) { __forest[__i] = __insertee; // refcount is OK since __insertee is now dead. return; } } } template _CharT rope<_CharT, _Alloc>:: _S_fetch(_RopeRep* __r, size_type __i) { __GC_CONST _CharT* __cstr = __r->_M_c_string; if (0 != __cstr) return __cstr[__i]; for(;;) { switch(__r->_M_tag) { case __detail::_S_concat: { _RopeConcatenation* __c = (_RopeConcatenation*)__r; _RopeRep* __left = __c->_M_left; size_t __left_len = __left->_M_size; if (__i >= __left_len) { __i -= __left_len; __r = __c->_M_right; } else __r = __left; } break; case __detail::_S_leaf: { _RopeLeaf* __l = (_RopeLeaf*)__r; return __l->_M_data[__i]; } case __detail::_S_function: case __detail::_S_substringfn: { _RopeFunction* __f = (_RopeFunction*)__r; _CharT __result; (*(__f->_M_fn))(__i, 1, &__result); return __result; } } } } #ifndef __GC // Return a uniquely referenced character slot for the given // position, or 0 if that's not possible. template _CharT* rope<_CharT, _Alloc>:: _S_fetch_ptr(_RopeRep* __r, size_type __i) { _RopeRep* __clrstack[__detail::_S_max_rope_depth]; size_t __csptr = 0; for(;;) { if (__r->_M_ref_count > 1) return 0; switch(__r->_M_tag) { case __detail::_S_concat: { _RopeConcatenation* __c = (_RopeConcatenation*)__r; _RopeRep* __left = __c->_M_left; size_t __left_len = __left->_M_size; if (__c->_M_c_string != 0) __clrstack[__csptr++] = __c; if (__i >= __left_len) { __i -= __left_len; __r = __c->_M_right; } else __r = __left; } break; case __detail::_S_leaf: { _RopeLeaf* __l = (_RopeLeaf*)__r; if (__l->_M_c_string != __l->_M_data && __l->_M_c_string != 0) __clrstack[__csptr++] = __l; while (__csptr > 0) { -- __csptr; _RopeRep* __d = __clrstack[__csptr]; __d->_M_free_c_string(); __d->_M_c_string = 0; } return __l->_M_data + __i; } case __detail::_S_function: case __detail::_S_substringfn: return 0; } } } #endif /* __GC */ // The following could be implemented trivially using // lexicographical_compare_3way. // We do a little more work to avoid dealing with rope iterators for // flat strings. template int rope<_CharT, _Alloc>:: _S_compare (const _RopeRep* __left, const _RopeRep* __right) { size_t __left_len; size_t __right_len; if (0 == __right) return 0 != __left; if (0 == __left) return -1; __left_len = __left->_M_size; __right_len = __right->_M_size; if (__detail::_S_leaf == __left->_M_tag) { _RopeLeaf* __l = (_RopeLeaf*) __left; if (__detail::_S_leaf == __right->_M_tag) { _RopeLeaf* __r = (_RopeLeaf*) __right; return lexicographical_compare_3way(__l->_M_data, __l->_M_data + __left_len, __r->_M_data, __r->_M_data + __right_len); } else { const_iterator __rstart(__right, 0); const_iterator __rend(__right, __right_len); return lexicographical_compare_3way(__l->_M_data, __l->_M_data + __left_len, __rstart, __rend); } } else { const_iterator __lstart(__left, 0); const_iterator __lend(__left, __left_len); if (__detail::_S_leaf == __right->_M_tag) { _RopeLeaf* __r = (_RopeLeaf*) __right; return lexicographical_compare_3way(__lstart, __lend, __r->_M_data, __r->_M_data + __right_len); } else { const_iterator __rstart(__right, 0); const_iterator __rend(__right, __right_len); return lexicographical_compare_3way(__lstart, __lend, __rstart, __rend); } } } // Assignment to reference proxies. template _Rope_char_ref_proxy<_CharT, _Alloc>& _Rope_char_ref_proxy<_CharT, _Alloc>:: operator=(_CharT __c) { _RopeRep* __old = _M_root->_M_tree_ptr; #ifndef __GC // First check for the case in which everything is uniquely // referenced. In that case we can do this destructively. _CharT* __ptr = _My_rope::_S_fetch_ptr(__old, _M_pos); if (0 != __ptr) { *__ptr = __c; return *this; } #endif _Self_destruct_ptr __left(_My_rope::_S_substring(__old, 0, _M_pos)); _Self_destruct_ptr __right(_My_rope::_S_substring(__old, _M_pos + 1, __old->_M_size)); _Self_destruct_ptr __result_left(_My_rope:: _S_destr_concat_char_iter(__left, &__c, 1)); _RopeRep* __result = _My_rope::_S_concat(__result_left, __right); #ifndef __GC _RopeRep::_S_unref(__old); #endif _M_root->_M_tree_ptr = __result; return *this; } template inline _Rope_char_ref_proxy<_CharT, _Alloc>:: operator _CharT() const { if (_M_current_valid) return _M_current; else return _My_rope::_S_fetch(_M_root->_M_tree_ptr, _M_pos); } template _Rope_char_ptr_proxy<_CharT, _Alloc> _Rope_char_ref_proxy<_CharT, _Alloc>:: operator&() const { return _Rope_char_ptr_proxy<_CharT, _Alloc>(*this); } template rope<_CharT, _Alloc>:: rope(size_t __n, _CharT __c, const allocator_type& __a) : _Base(__a) { rope<_CharT,_Alloc> __result; const size_t __exponentiate_threshold = 32; size_t __exponent; size_t __rest; _CharT* __rest_buffer; _RopeRep* __remainder; rope<_CharT, _Alloc> __remainder_rope; if (0 == __n) return; __exponent = __n / __exponentiate_threshold; __rest = __n % __exponentiate_threshold; if (0 == __rest) __remainder = 0; else { __rest_buffer = this->_Data_allocate(_S_rounded_up_size(__rest)); __uninitialized_fill_n_a(__rest_buffer, __rest, __c, _M_get_allocator()); _S_cond_store_eos(__rest_buffer[__rest]); __try { __remainder = _S_new_RopeLeaf(__rest_buffer, __rest, _M_get_allocator()); } __catch(...) { _RopeRep::__STL_FREE_STRING(__rest_buffer, __rest, _M_get_allocator()); __throw_exception_again; } } __remainder_rope._M_tree_ptr = __remainder; if (__exponent != 0) { _CharT* __base_buffer = this->_Data_allocate(_S_rounded_up_size(__exponentiate_threshold)); _RopeLeaf* __base_leaf; rope __base_rope; __uninitialized_fill_n_a(__base_buffer, __exponentiate_threshold, __c, _M_get_allocator()); _S_cond_store_eos(__base_buffer[__exponentiate_threshold]); __try { __base_leaf = _S_new_RopeLeaf(__base_buffer, __exponentiate_threshold, _M_get_allocator()); } __catch(...) { _RopeRep::__STL_FREE_STRING(__base_buffer, __exponentiate_threshold, _M_get_allocator()); __throw_exception_again; } __base_rope._M_tree_ptr = __base_leaf; if (1 == __exponent) __result = __base_rope; else __result = power(__base_rope, __exponent, _Rope_Concat_fn<_CharT, _Alloc>()); if (0 != __remainder) __result += __remainder_rope; } else __result = __remainder_rope; this->_M_tree_ptr = __result._M_tree_ptr; this->_M_tree_ptr->_M_ref_nonnil(); } template _CharT rope<_CharT, _Alloc>::_S_empty_c_str[1]; template const _CharT* rope<_CharT, _Alloc>:: c_str() const { if (0 == this->_M_tree_ptr) { _S_empty_c_str[0] = _S_eos((_CharT*)0); // Possibly redundant, // but probably fast. return _S_empty_c_str; } __gthread_mutex_lock (&this->_M_tree_ptr->_M_c_string_lock); __GC_CONST _CharT* __result = this->_M_tree_ptr->_M_c_string; if (0 == __result) { size_t __s = size(); __result = this->_Data_allocate(__s + 1); _S_flatten(this->_M_tree_ptr, __result); __result[__s] = _S_eos((_CharT*)0); this->_M_tree_ptr->_M_c_string = __result; } __gthread_mutex_unlock (&this->_M_tree_ptr->_M_c_string_lock); return(__result); } template const _CharT* rope<_CharT, _Alloc>:: replace_with_c_str() { if (0 == this->_M_tree_ptr) { _S_empty_c_str[0] = _S_eos((_CharT*)0); return _S_empty_c_str; } __GC_CONST _CharT* __old_c_string = this->_M_tree_ptr->_M_c_string; if (__detail::_S_leaf == this->_M_tree_ptr->_M_tag && 0 != __old_c_string) return(__old_c_string); size_t __s = size(); _CharT* __result = this->_Data_allocate(_S_rounded_up_size(__s)); _S_flatten(this->_M_tree_ptr, __result); __result[__s] = _S_eos((_CharT*)0); this->_M_tree_ptr->_M_unref_nonnil(); this->_M_tree_ptr = _S_new_RopeLeaf(__result, __s, this->_M_get_allocator()); return(__result); } // Algorithm specializations. More should be added. template // was templated on CharT and Alloc void // VC++ workaround _Rope_rotate(_Rope_iterator __first, _Rope_iterator __middle, _Rope_iterator __last) { typedef typename _Rope_iterator::value_type _CharT; typedef typename _Rope_iterator::_allocator_type _Alloc; rope<_CharT, _Alloc>& __r(__first.container()); rope<_CharT, _Alloc> __prefix = __r.substr(0, __first.index()); rope<_CharT, _Alloc> __suffix = __r.substr(__last.index(), __r.size() - __last.index()); rope<_CharT, _Alloc> __part1 = __r.substr(__middle.index(), __last.index() - __middle.index()); rope<_CharT, _Alloc> __part2 = __r.substr(__first.index(), __middle.index() - __first.index()); __r = __prefix; __r += __part1; __r += __part2; __r += __suffix; } #if !defined(__GNUC__) // Appears to confuse g++ inline void rotate(_Rope_iterator __first, _Rope_iterator __middle, _Rope_iterator __last) { _Rope_rotate(__first, __middle, __last); } #endif # if 0 // Probably not useful for several reasons: // - for SGIs 7.1 compiler and probably some others, // this forces lots of rope instantiations, creating a // code bloat and compile time problem. (Fixed in 7.2.) // - wchar_t is 4 bytes wide on most UNIX platforms, making it // unattractive for unicode strings. Unsigned short may be a better // character type. inline void rotate(_Rope_iterator __first, _Rope_iterator __middle, _Rope_iterator __last) { _Rope_rotate(__first, __middle, __last); } # endif _GLIBCXX_END_NAMESPACE_VERSION } // namespace PKNd]^ UVUV 8/ext/ropenu[// SGI's rope class -*- C++ -*- // Copyright (C) 2001-2018 Free Software Foundation, Inc. // // This file is part of the GNU ISO C++ Library. This library is free // software; you can redistribute it and/or modify it under the // terms of the GNU General Public License as published by the // Free Software Foundation; either version 3, or (at your option) // any later version. // This library is distributed in the hope that it will be useful, // but WITHOUT ANY WARRANTY; without even the implied warranty of // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the // GNU General Public License for more details. // Under Section 7 of GPL version 3, you are granted additional // permissions described in the GCC Runtime Library Exception, version // 3.1, as published by the Free Software Foundation. // You should have received a copy of the GNU General Public License and // a copy of the GCC Runtime Library Exception along with this program; // see the files COPYING3 and COPYING.RUNTIME respectively. If not, see // . /* * Copyright (c) 1997 * Silicon Graphics Computer Systems, Inc. * * Permission to use, copy, modify, distribute and sell this software * and its documentation for any purpose is hereby granted without fee, * provided that the above copyright notice appear in all copies and * that both that copyright notice and this permission notice appear * in supporting documentation. Silicon Graphics makes no * representations about the suitability of this software for any * purpose. It is provided "as is" without express or implied warranty. */ /** @file ext/rope * This file is a GNU extension to the Standard C++ Library (possibly * containing extensions from the HP/SGI STL subset). */ #ifndef _ROPE #define _ROPE 1 #pragma GCC system_header #include #include #include #include #include #include #include #include #include # ifdef __GC # define __GC_CONST const # else # define __GC_CONST // constant except for deallocation # endif #include // For uninitialized_copy_n namespace __gnu_cxx _GLIBCXX_VISIBILITY(default) { _GLIBCXX_BEGIN_NAMESPACE_VERSION namespace __detail { enum { _S_max_rope_depth = 45 }; enum _Tag {_S_leaf, _S_concat, _S_substringfn, _S_function}; } // namespace __detail using std::size_t; using std::ptrdiff_t; using std::allocator; using std::_Destroy; // See libstdc++/36832. template void _Destroy_const(_ForwardIterator __first, _ForwardIterator __last, _Allocator __alloc) { for (; __first != __last; ++__first) __alloc.destroy(&*__first); } template inline void _Destroy_const(_ForwardIterator __first, _ForwardIterator __last, allocator<_Tp>) { _Destroy(__first, __last); } // The _S_eos function is used for those functions that // convert to/from C-like strings to detect the end of the string. // The end-of-C-string character. // This is what the draft standard says it should be. template inline _CharT _S_eos(_CharT*) { return _CharT(); } // Test for basic character types. // For basic character types leaves having a trailing eos. template inline bool _S_is_basic_char_type(_CharT*) { return false; } template inline bool _S_is_one_byte_char_type(_CharT*) { return false; } inline bool _S_is_basic_char_type(char*) { return true; } inline bool _S_is_one_byte_char_type(char*) { return true; } inline bool _S_is_basic_char_type(wchar_t*) { return true; } // Store an eos iff _CharT is a basic character type. // Do not reference _S_eos if it isn't. template inline void _S_cond_store_eos(_CharT&) { } inline void _S_cond_store_eos(char& __c) { __c = 0; } inline void _S_cond_store_eos(wchar_t& __c) { __c = 0; } // char_producers are logically functions that generate a section of // a string. These can be converted to ropes. The resulting rope // invokes the char_producer on demand. This allows, for example, // files to be viewed as ropes without reading the entire file. template class char_producer { public: virtual ~char_producer() { } virtual void operator()(size_t __start_pos, size_t __len, _CharT* __buffer) = 0; // Buffer should really be an arbitrary output iterator. // That way we could flatten directly into an ostream, etc. // This is thoroughly impossible, since iterator types don't // have runtime descriptions. }; // Sequence buffers: // // Sequence must provide an append operation that appends an // array to the sequence. Sequence buffers are useful only if // appending an entire array is cheaper than appending element by element. // This is true for many string representations. // This should perhaps inherit from ostream // and be implemented correspondingly, so that they can be used // for formatted. For the sake of portability, we don't do this yet. // // For now, sequence buffers behave as output iterators. But they also // behave a little like basic_ostringstream and a // little like containers. template class sequence_buffer : public std::iterator { public: typedef typename _Sequence::value_type value_type; protected: _Sequence* _M_prefix; value_type _M_buffer[_Buf_sz]; size_t _M_buf_count; public: void flush() { _M_prefix->append(_M_buffer, _M_buffer + _M_buf_count); _M_buf_count = 0; } ~sequence_buffer() { flush(); } sequence_buffer() : _M_prefix(0), _M_buf_count(0) { } sequence_buffer(const sequence_buffer& __x) { _M_prefix = __x._M_prefix; _M_buf_count = __x._M_buf_count; std::copy(__x._M_buffer, __x._M_buffer + __x._M_buf_count, _M_buffer); } sequence_buffer(sequence_buffer& __x) { __x.flush(); _M_prefix = __x._M_prefix; _M_buf_count = 0; } sequence_buffer(_Sequence& __s) : _M_prefix(&__s), _M_buf_count(0) { } sequence_buffer& operator=(sequence_buffer& __x) { __x.flush(); _M_prefix = __x._M_prefix; _M_buf_count = 0; return *this; } sequence_buffer& operator=(const sequence_buffer& __x) { _M_prefix = __x._M_prefix; _M_buf_count = __x._M_buf_count; std::copy(__x._M_buffer, __x._M_buffer + __x._M_buf_count, _M_buffer); return *this; } void push_back(value_type __x) { if (_M_buf_count < _Buf_sz) { _M_buffer[_M_buf_count] = __x; ++_M_buf_count; } else { flush(); _M_buffer[0] = __x; _M_buf_count = 1; } } void append(value_type* __s, size_t __len) { if (__len + _M_buf_count <= _Buf_sz) { size_t __i = _M_buf_count; for (size_t __j = 0; __j < __len; __i++, __j++) _M_buffer[__i] = __s[__j]; _M_buf_count += __len; } else if (0 == _M_buf_count) _M_prefix->append(__s, __s + __len); else { flush(); append(__s, __len); } } sequence_buffer& write(value_type* __s, size_t __len) { append(__s, __len); return *this; } sequence_buffer& put(value_type __x) { push_back(__x); return *this; } sequence_buffer& operator=(const value_type& __rhs) { push_back(__rhs); return *this; } sequence_buffer& operator*() { return *this; } sequence_buffer& operator++() { return *this; } sequence_buffer operator++(int) { return *this; } }; // The following should be treated as private, at least for now. template class _Rope_char_consumer { public: // If we had member templates, these should not be virtual. // For now we need to use run-time parametrization where // compile-time would do. Hence this should all be private // for now. // The symmetry with char_producer is accidental and temporary. virtual ~_Rope_char_consumer() { } virtual bool operator()(const _CharT* __buffer, size_t __len) = 0; }; // First a lot of forward declarations. The standard seems to require // much stricter "declaration before use" than many of the implementations // that preceded it. template > class rope; template struct _Rope_RopeConcatenation; template struct _Rope_RopeLeaf; template struct _Rope_RopeFunction; template struct _Rope_RopeSubstring; template class _Rope_iterator; template class _Rope_const_iterator; template class _Rope_char_ref_proxy; template class _Rope_char_ptr_proxy; template bool operator==(const _Rope_char_ptr_proxy<_CharT, _Alloc>& __x, const _Rope_char_ptr_proxy<_CharT, _Alloc>& __y); template _Rope_const_iterator<_CharT, _Alloc> operator-(const _Rope_const_iterator<_CharT, _Alloc>& __x, ptrdiff_t __n); template _Rope_const_iterator<_CharT, _Alloc> operator+(const _Rope_const_iterator<_CharT, _Alloc>& __x, ptrdiff_t __n); template _Rope_const_iterator<_CharT, _Alloc> operator+(ptrdiff_t __n, const _Rope_const_iterator<_CharT, _Alloc>& __x); template bool operator==(const _Rope_const_iterator<_CharT, _Alloc>& __x, const _Rope_const_iterator<_CharT, _Alloc>& __y); template bool operator<(const _Rope_const_iterator<_CharT, _Alloc>& __x, const _Rope_const_iterator<_CharT, _Alloc>& __y); template ptrdiff_t operator-(const _Rope_const_iterator<_CharT, _Alloc>& __x, const _Rope_const_iterator<_CharT, _Alloc>& __y); template _Rope_iterator<_CharT, _Alloc> operator-(const _Rope_iterator<_CharT, _Alloc>& __x, ptrdiff_t __n); template _Rope_iterator<_CharT, _Alloc> operator+(const _Rope_iterator<_CharT, _Alloc>& __x, ptrdiff_t __n); template _Rope_iterator<_CharT, _Alloc> operator+(ptrdiff_t __n, const _Rope_iterator<_CharT, _Alloc>& __x); template bool operator==(const _Rope_iterator<_CharT, _Alloc>& __x, const _Rope_iterator<_CharT, _Alloc>& __y); template bool operator<(const _Rope_iterator<_CharT, _Alloc>& __x, const _Rope_iterator<_CharT, _Alloc>& __y); template ptrdiff_t operator-(const _Rope_iterator<_CharT, _Alloc>& __x, const _Rope_iterator<_CharT, _Alloc>& __y); template rope<_CharT, _Alloc> operator+(const rope<_CharT, _Alloc>& __left, const rope<_CharT, _Alloc>& __right); template rope<_CharT, _Alloc> operator+(const rope<_CharT, _Alloc>& __left, const _CharT* __right); template rope<_CharT, _Alloc> operator+(const rope<_CharT, _Alloc>& __left, _CharT __right); // Some helpers, so we can use power on ropes. // See below for why this isn't local to the implementation. // This uses a nonstandard refcount convention. // The result has refcount 0. template struct _Rope_Concat_fn : public std::binary_function, rope<_CharT, _Alloc>, rope<_CharT, _Alloc> > { rope<_CharT, _Alloc> operator()(const rope<_CharT, _Alloc>& __x, const rope<_CharT, _Alloc>& __y) { return __x + __y; } }; template inline rope<_CharT, _Alloc> identity_element(_Rope_Concat_fn<_CharT, _Alloc>) { return rope<_CharT, _Alloc>(); } // Class _Refcount_Base provides a type, _RC_t, a data member, // _M_ref_count, and member functions _M_incr and _M_decr, which perform // atomic preincrement/predecrement. The constructor initializes // _M_ref_count. struct _Refcount_Base { // The type _RC_t typedef size_t _RC_t; // The data member _M_ref_count volatile _RC_t _M_ref_count; // Constructor #ifdef __GTHREAD_MUTEX_INIT __gthread_mutex_t _M_ref_count_lock = __GTHREAD_MUTEX_INIT; #else __gthread_mutex_t _M_ref_count_lock; #endif _Refcount_Base(_RC_t __n) : _M_ref_count(__n) { #ifndef __GTHREAD_MUTEX_INIT #ifdef __GTHREAD_MUTEX_INIT_FUNCTION __GTHREAD_MUTEX_INIT_FUNCTION (&_M_ref_count_lock); #else #error __GTHREAD_MUTEX_INIT or __GTHREAD_MUTEX_INIT_FUNCTION should be defined by gthr.h abstraction layer, report problem to libstdc++@gcc.gnu.org. #endif #endif } #ifndef __GTHREAD_MUTEX_INIT ~_Refcount_Base() { __gthread_mutex_destroy(&_M_ref_count_lock); } #endif void _M_incr() { __gthread_mutex_lock(&_M_ref_count_lock); ++_M_ref_count; __gthread_mutex_unlock(&_M_ref_count_lock); } _RC_t _M_decr() { __gthread_mutex_lock(&_M_ref_count_lock); volatile _RC_t __tmp = --_M_ref_count; __gthread_mutex_unlock(&_M_ref_count_lock); return __tmp; } }; // // What follows should really be local to rope. Unfortunately, // that doesn't work, since it makes it impossible to define generic // equality on rope iterators. According to the draft standard, the // template parameters for such an equality operator cannot be inferred // from the occurrence of a member class as a parameter. // (SGI compilers in fact allow this, but the __result wouldn't be // portable.) // Similarly, some of the static member functions are member functions // only to avoid polluting the global namespace, and to circumvent // restrictions on type inference for template functions. // // // The internal data structure for representing a rope. This is // private to the implementation. A rope is really just a pointer // to one of these. // // A few basic functions for manipulating this data structure // are members of _RopeRep. Most of the more complex algorithms // are implemented as rope members. // // Some of the static member functions of _RopeRep have identically // named functions in rope that simply invoke the _RopeRep versions. #define __ROPE_DEFINE_ALLOCS(__a) \ __ROPE_DEFINE_ALLOC(_CharT,_Data) /* character data */ \ typedef _Rope_RopeConcatenation<_CharT,__a> __C; \ __ROPE_DEFINE_ALLOC(__C,_C) \ typedef _Rope_RopeLeaf<_CharT,__a> __L; \ __ROPE_DEFINE_ALLOC(__L,_L) \ typedef _Rope_RopeFunction<_CharT,__a> __F; \ __ROPE_DEFINE_ALLOC(__F,_F) \ typedef _Rope_RopeSubstring<_CharT,__a> __S; \ __ROPE_DEFINE_ALLOC(__S,_S) // Internal rope nodes potentially store a copy of the allocator // instance used to allocate them. This is mostly redundant. // But the alternative would be to pass allocator instances around // in some form to nearly all internal functions, since any pointer // assignment may result in a zero reference count and thus require // deallocation. #define __STATIC_IF_SGI_ALLOC /* not static */ template struct _Rope_rep_base : public _Alloc { typedef _Alloc allocator_type; allocator_type get_allocator() const { return *static_cast(this); } allocator_type& _M_get_allocator() { return *static_cast<_Alloc*>(this); } const allocator_type& _M_get_allocator() const { return *static_cast(this); } _Rope_rep_base(size_t __size, const allocator_type&) : _M_size(__size) { } size_t _M_size; # define __ROPE_DEFINE_ALLOC(_Tp, __name) \ typedef typename \ _Alloc::template rebind<_Tp>::other __name##Alloc; \ static _Tp* __name##_allocate(size_t __n) \ { return __name##Alloc().allocate(__n); } \ static void __name##_deallocate(_Tp *__p, size_t __n) \ { __name##Alloc().deallocate(__p, __n); } __ROPE_DEFINE_ALLOCS(_Alloc) # undef __ROPE_DEFINE_ALLOC }; template struct _Rope_RopeRep : public _Rope_rep_base<_CharT, _Alloc> # ifndef __GC , _Refcount_Base # endif { public: __detail::_Tag _M_tag:8; bool _M_is_balanced:8; unsigned char _M_depth; __GC_CONST _CharT* _M_c_string; #ifdef __GTHREAD_MUTEX_INIT __gthread_mutex_t _M_c_string_lock = __GTHREAD_MUTEX_INIT; #else __gthread_mutex_t _M_c_string_lock; #endif /* Flattened version of string, if needed. */ /* typically 0. */ /* If it's not 0, then the memory is owned */ /* by this node. */ /* In the case of a leaf, this may point to */ /* the same memory as the data field. */ typedef typename _Rope_rep_base<_CharT, _Alloc>::allocator_type allocator_type; using _Rope_rep_base<_CharT, _Alloc>::get_allocator; using _Rope_rep_base<_CharT, _Alloc>::_M_get_allocator; _Rope_RopeRep(__detail::_Tag __t, int __d, bool __b, size_t __size, const allocator_type& __a) : _Rope_rep_base<_CharT, _Alloc>(__size, __a), #ifndef __GC _Refcount_Base(1), #endif _M_tag(__t), _M_is_balanced(__b), _M_depth(__d), _M_c_string(0) #ifdef __GTHREAD_MUTEX_INIT { } #else { __GTHREAD_MUTEX_INIT_FUNCTION (&_M_c_string_lock); } ~_Rope_RopeRep() { __gthread_mutex_destroy (&_M_c_string_lock); } #endif #ifdef __GC void _M_incr () { } #endif static void _S_free_string(__GC_CONST _CharT*, size_t __len, allocator_type& __a); #define __STL_FREE_STRING(__s, __l, __a) _S_free_string(__s, __l, __a); // Deallocate data section of a leaf. // This shouldn't be a member function. // But its hard to do anything else at the // moment, because it's templatized w.r.t. // an allocator. // Does nothing if __GC is defined. #ifndef __GC void _M_free_c_string(); void _M_free_tree(); // Deallocate t. Assumes t is not 0. void _M_unref_nonnil() { if (0 == _M_decr()) _M_free_tree(); } void _M_ref_nonnil() { _M_incr(); } static void _S_unref(_Rope_RopeRep* __t) { if (0 != __t) __t->_M_unref_nonnil(); } static void _S_ref(_Rope_RopeRep* __t) { if (0 != __t) __t->_M_incr(); } static void _S_free_if_unref(_Rope_RopeRep* __t) { if (0 != __t && 0 == __t->_M_ref_count) __t->_M_free_tree(); } # else /* __GC */ void _M_unref_nonnil() { } void _M_ref_nonnil() { } static void _S_unref(_Rope_RopeRep*) { } static void _S_ref(_Rope_RopeRep*) { } static void _S_free_if_unref(_Rope_RopeRep*) { } # endif protected: _Rope_RopeRep& operator=(const _Rope_RopeRep&); _Rope_RopeRep(const _Rope_RopeRep&); }; template struct _Rope_RopeLeaf : public _Rope_RopeRep<_CharT, _Alloc> { public: // Apparently needed by VC++ // The data fields of leaves are allocated with some // extra space, to accommodate future growth and for basic // character types, to hold a trailing eos character. enum { _S_alloc_granularity = 8 }; static size_t _S_rounded_up_size(size_t __n) { size_t __size_with_eos; if (_S_is_basic_char_type((_CharT*)0)) __size_with_eos = __n + 1; else __size_with_eos = __n; #ifdef __GC return __size_with_eos; #else // Allow slop for in-place expansion. return ((__size_with_eos + size_t(_S_alloc_granularity) - 1) &~ (size_t(_S_alloc_granularity) - 1)); #endif } __GC_CONST _CharT* _M_data; /* Not necessarily 0 terminated. */ /* The allocated size is */ /* _S_rounded_up_size(size), except */ /* in the GC case, in which it */ /* doesn't matter. */ typedef typename _Rope_rep_base<_CharT,_Alloc>::allocator_type allocator_type; _Rope_RopeLeaf(__GC_CONST _CharT* __d, size_t __size, const allocator_type& __a) : _Rope_RopeRep<_CharT, _Alloc>(__detail::_S_leaf, 0, true, __size, __a), _M_data(__d) { if (_S_is_basic_char_type((_CharT *)0)) { // already eos terminated. this->_M_c_string = __d; } } // The constructor assumes that d has been allocated with // the proper allocator and the properly padded size. // In contrast, the destructor deallocates the data: #ifndef __GC ~_Rope_RopeLeaf() throw() { if (_M_data != this->_M_c_string) this->_M_free_c_string(); this->__STL_FREE_STRING(_M_data, this->_M_size, this->_M_get_allocator()); } #endif protected: _Rope_RopeLeaf& operator=(const _Rope_RopeLeaf&); _Rope_RopeLeaf(const _Rope_RopeLeaf&); }; template struct _Rope_RopeConcatenation : public _Rope_RopeRep<_CharT, _Alloc> { public: _Rope_RopeRep<_CharT, _Alloc>* _M_left; _Rope_RopeRep<_CharT, _Alloc>* _M_right; typedef typename _Rope_rep_base<_CharT, _Alloc>::allocator_type allocator_type; _Rope_RopeConcatenation(_Rope_RopeRep<_CharT, _Alloc>* __l, _Rope_RopeRep<_CharT, _Alloc>* __r, const allocator_type& __a) : _Rope_RopeRep<_CharT, _Alloc>(__detail::_S_concat, std::max(__l->_M_depth, __r->_M_depth) + 1, false, __l->_M_size + __r->_M_size, __a), _M_left(__l), _M_right(__r) { } #ifndef __GC ~_Rope_RopeConcatenation() throw() { this->_M_free_c_string(); _M_left->_M_unref_nonnil(); _M_right->_M_unref_nonnil(); } #endif protected: _Rope_RopeConcatenation& operator=(const _Rope_RopeConcatenation&); _Rope_RopeConcatenation(const _Rope_RopeConcatenation&); }; template struct _Rope_RopeFunction : public _Rope_RopeRep<_CharT, _Alloc> { public: char_producer<_CharT>* _M_fn; #ifndef __GC bool _M_delete_when_done; // Char_producer is owned by the // rope and should be explicitly // deleted when the rope becomes // inaccessible. #else // In the GC case, we either register the rope for // finalization, or not. Thus the field is unnecessary; // the information is stored in the collector data structures. // We do need a finalization procedure to be invoked by the // collector. static void _S_fn_finalization_proc(void * __tree, void *) { delete ((_Rope_RopeFunction *)__tree) -> _M_fn; } #endif typedef typename _Rope_rep_base<_CharT, _Alloc>::allocator_type allocator_type; _Rope_RopeFunction(char_producer<_CharT>* __f, size_t __size, bool __d, const allocator_type& __a) : _Rope_RopeRep<_CharT, _Alloc>(__detail::_S_function, 0, true, __size, __a) , _M_fn(__f) #ifndef __GC , _M_delete_when_done(__d) #endif { #ifdef __GC if (__d) { GC_REGISTER_FINALIZER(this, _Rope_RopeFunction:: _S_fn_finalization_proc, 0, 0, 0); } #endif } #ifndef __GC ~_Rope_RopeFunction() throw() { this->_M_free_c_string(); if (_M_delete_when_done) delete _M_fn; } # endif protected: _Rope_RopeFunction& operator=(const _Rope_RopeFunction&); _Rope_RopeFunction(const _Rope_RopeFunction&); }; // Substring results are usually represented using just // concatenation nodes. But in the case of very long flat ropes // or ropes with a functional representation that isn't practical. // In that case, we represent the __result as a special case of // RopeFunction, whose char_producer points back to the rope itself. // In all cases except repeated substring operations and // deallocation, we treat the __result as a RopeFunction. template struct _Rope_RopeSubstring : public _Rope_RopeFunction<_CharT, _Alloc>, public char_producer<_CharT> { public: // XXX this whole class should be rewritten. _Rope_RopeRep<_CharT,_Alloc>* _M_base; // not 0 size_t _M_start; virtual void operator()(size_t __start_pos, size_t __req_len, _CharT* __buffer) { switch(_M_base->_M_tag) { case __detail::_S_function: case __detail::_S_substringfn: { char_producer<_CharT>* __fn = ((_Rope_RopeFunction<_CharT,_Alloc>*)_M_base)->_M_fn; (*__fn)(__start_pos + _M_start, __req_len, __buffer); } break; case __detail::_S_leaf: { __GC_CONST _CharT* __s = ((_Rope_RopeLeaf<_CharT,_Alloc>*)_M_base)->_M_data; uninitialized_copy_n(__s + __start_pos + _M_start, __req_len, __buffer); } break; default: break; } } typedef typename _Rope_rep_base<_CharT, _Alloc>::allocator_type allocator_type; _Rope_RopeSubstring(_Rope_RopeRep<_CharT, _Alloc>* __b, size_t __s, size_t __l, const allocator_type& __a) : _Rope_RopeFunction<_CharT, _Alloc>(this, __l, false, __a), char_producer<_CharT>(), _M_base(__b), _M_start(__s) { #ifndef __GC _M_base->_M_ref_nonnil(); #endif this->_M_tag = __detail::_S_substringfn; } virtual ~_Rope_RopeSubstring() throw() { #ifndef __GC _M_base->_M_unref_nonnil(); // _M_free_c_string(); -- done by parent class #endif } }; // Self-destructing pointers to Rope_rep. // These are not conventional smart pointers. Their // only purpose in life is to ensure that unref is called // on the pointer either at normal exit or if an exception // is raised. It is the caller's responsibility to // adjust reference counts when these pointers are initialized // or assigned to. (This convention significantly reduces // the number of potentially expensive reference count // updates.) #ifndef __GC template struct _Rope_self_destruct_ptr { _Rope_RopeRep<_CharT, _Alloc>* _M_ptr; ~_Rope_self_destruct_ptr() { _Rope_RopeRep<_CharT, _Alloc>::_S_unref(_M_ptr); } #if __cpp_exceptions _Rope_self_destruct_ptr() : _M_ptr(0) { } #else _Rope_self_destruct_ptr() { } #endif _Rope_self_destruct_ptr(_Rope_RopeRep<_CharT, _Alloc>* __p) : _M_ptr(__p) { } _Rope_RopeRep<_CharT, _Alloc>& operator*() { return *_M_ptr; } _Rope_RopeRep<_CharT, _Alloc>* operator->() { return _M_ptr; } operator _Rope_RopeRep<_CharT, _Alloc>*() { return _M_ptr; } _Rope_self_destruct_ptr& operator=(_Rope_RopeRep<_CharT, _Alloc>* __x) { _M_ptr = __x; return *this; } }; #endif // Dereferencing a nonconst iterator has to return something // that behaves almost like a reference. It's not possible to // return an actual reference since assignment requires extra // work. And we would get into the same problems as with the // CD2 version of basic_string. template class _Rope_char_ref_proxy { friend class rope<_CharT, _Alloc>; friend class _Rope_iterator<_CharT, _Alloc>; friend class _Rope_char_ptr_proxy<_CharT, _Alloc>; #ifdef __GC typedef _Rope_RopeRep<_CharT, _Alloc>* _Self_destruct_ptr; #else typedef _Rope_self_destruct_ptr<_CharT, _Alloc> _Self_destruct_ptr; #endif typedef _Rope_RopeRep<_CharT, _Alloc> _RopeRep; typedef rope<_CharT, _Alloc> _My_rope; size_t _M_pos; _CharT _M_current; bool _M_current_valid; _My_rope* _M_root; // The whole rope. public: _Rope_char_ref_proxy(_My_rope* __r, size_t __p) : _M_pos(__p), _M_current(), _M_current_valid(false), _M_root(__r) { } _Rope_char_ref_proxy(const _Rope_char_ref_proxy& __x) : _M_pos(__x._M_pos), _M_current(__x._M_current), _M_current_valid(false), _M_root(__x._M_root) { } // Don't preserve cache if the reference can outlive the // expression. We claim that's not possible without calling // a copy constructor or generating reference to a proxy // reference. We declare the latter to have undefined semantics. _Rope_char_ref_proxy(_My_rope* __r, size_t __p, _CharT __c) : _M_pos(__p), _M_current(__c), _M_current_valid(true), _M_root(__r) { } inline operator _CharT () const; _Rope_char_ref_proxy& operator=(_CharT __c); _Rope_char_ptr_proxy<_CharT, _Alloc> operator&() const; _Rope_char_ref_proxy& operator=(const _Rope_char_ref_proxy& __c) { return operator=((_CharT)__c); } }; template inline void swap(_Rope_char_ref_proxy <_CharT, __Alloc > __a, _Rope_char_ref_proxy <_CharT, __Alloc > __b) { _CharT __tmp = __a; __a = __b; __b = __tmp; } template class _Rope_char_ptr_proxy { // XXX this class should be rewritten. friend class _Rope_char_ref_proxy<_CharT, _Alloc>; size_t _M_pos; rope<_CharT,_Alloc>* _M_root; // The whole rope. public: _Rope_char_ptr_proxy(const _Rope_char_ref_proxy<_CharT,_Alloc>& __x) : _M_pos(__x._M_pos), _M_root(__x._M_root) { } _Rope_char_ptr_proxy(const _Rope_char_ptr_proxy& __x) : _M_pos(__x._M_pos), _M_root(__x._M_root) { } _Rope_char_ptr_proxy() { } _Rope_char_ptr_proxy(_CharT* __x) : _M_root(0), _M_pos(0) { } _Rope_char_ptr_proxy& operator=(const _Rope_char_ptr_proxy& __x) { _M_pos = __x._M_pos; _M_root = __x._M_root; return *this; } template friend bool operator==(const _Rope_char_ptr_proxy<_CharT2, _Alloc2>& __x, const _Rope_char_ptr_proxy<_CharT2, _Alloc2>& __y); _Rope_char_ref_proxy<_CharT, _Alloc> operator*() const { return _Rope_char_ref_proxy<_CharT, _Alloc>(_M_root, _M_pos); } }; // Rope iterators: // Unlike in the C version, we cache only part of the stack // for rope iterators, since they must be efficiently copyable. // When we run out of cache, we have to reconstruct the iterator // value. // Pointers from iterators are not included in reference counts. // Iterators are assumed to be thread private. Ropes can // be shared. template class _Rope_iterator_base : public std::iterator { friend class rope<_CharT, _Alloc>; public: typedef _Alloc _allocator_type; // used in _Rope_rotate, VC++ workaround typedef _Rope_RopeRep<_CharT, _Alloc> _RopeRep; // Borland doesn't want this to be protected. protected: enum { _S_path_cache_len = 4 }; // Must be <= 9. enum { _S_iterator_buf_len = 15 }; size_t _M_current_pos; _RopeRep* _M_root; // The whole rope. size_t _M_leaf_pos; // Starting position for current leaf __GC_CONST _CharT* _M_buf_start; // Buffer possibly // containing current char. __GC_CONST _CharT* _M_buf_ptr; // Pointer to current char in buffer. // != 0 ==> buffer valid. __GC_CONST _CharT* _M_buf_end; // One past __last valid char in buffer. // What follows is the path cache. We go out of our // way to make this compact. // Path_end contains the bottom section of the path from // the root to the current leaf. const _RopeRep* _M_path_end[_S_path_cache_len]; int _M_leaf_index; // Last valid __pos in path_end; // _M_path_end[0] ... _M_path_end[leaf_index-1] // point to concatenation nodes. unsigned char _M_path_directions; // (path_directions >> __i) & 1 is 1 // iff we got from _M_path_end[leaf_index - __i - 1] // to _M_path_end[leaf_index - __i] by going to the // __right. Assumes path_cache_len <= 9. _CharT _M_tmp_buf[_S_iterator_buf_len]; // Short buffer for surrounding chars. // This is useful primarily for // RopeFunctions. We put the buffer // here to avoid locking in the // multithreaded case. // The cached path is generally assumed to be valid // only if the buffer is valid. static void _S_setbuf(_Rope_iterator_base& __x); // Set buffer contents given // path cache. static void _S_setcache(_Rope_iterator_base& __x); // Set buffer contents and // path cache. static void _S_setcache_for_incr(_Rope_iterator_base& __x); // As above, but assumes path // cache is valid for previous posn. _Rope_iterator_base() { } _Rope_iterator_base(_RopeRep* __root, size_t __pos) : _M_current_pos(__pos), _M_root(__root), _M_buf_ptr(0) { } void _M_incr(size_t __n); void _M_decr(size_t __n); public: size_t index() const { return _M_current_pos; } _Rope_iterator_base(const _Rope_iterator_base& __x) { if (0 != __x._M_buf_ptr) *this = __x; else { _M_current_pos = __x._M_current_pos; _M_root = __x._M_root; _M_buf_ptr = 0; } } }; template class _Rope_iterator; template class _Rope_const_iterator : public _Rope_iterator_base<_CharT, _Alloc> { friend class rope<_CharT, _Alloc>; protected: typedef _Rope_RopeRep<_CharT, _Alloc> _RopeRep; // The one from the base class may not be directly visible. _Rope_const_iterator(const _RopeRep* __root, size_t __pos) : _Rope_iterator_base<_CharT, _Alloc>(const_cast<_RopeRep*>(__root), __pos) // Only nonconst iterators modify root ref count { } public: typedef _CharT reference; // Really a value. Returning a reference // Would be a mess, since it would have // to be included in refcount. typedef const _CharT* pointer; public: _Rope_const_iterator() { } _Rope_const_iterator(const _Rope_const_iterator& __x) : _Rope_iterator_base<_CharT,_Alloc>(__x) { } _Rope_const_iterator(const _Rope_iterator<_CharT,_Alloc>& __x); _Rope_const_iterator(const rope<_CharT, _Alloc>& __r, size_t __pos) : _Rope_iterator_base<_CharT,_Alloc>(__r._M_tree_ptr, __pos) { } _Rope_const_iterator& operator=(const _Rope_const_iterator& __x) { if (0 != __x._M_buf_ptr) *(static_cast<_Rope_iterator_base<_CharT, _Alloc>*>(this)) = __x; else { this->_M_current_pos = __x._M_current_pos; this->_M_root = __x._M_root; this->_M_buf_ptr = 0; } return(*this); } reference operator*() { if (0 == this->_M_buf_ptr) this->_S_setcache(*this); return *this->_M_buf_ptr; } // Without this const version, Rope iterators do not meet the // requirements of an Input Iterator. reference operator*() const { return *const_cast<_Rope_const_iterator&>(*this); } _Rope_const_iterator& operator++() { __GC_CONST _CharT* __next; if (0 != this->_M_buf_ptr && (__next = this->_M_buf_ptr + 1) < this->_M_buf_end) { this->_M_buf_ptr = __next; ++this->_M_current_pos; } else this->_M_incr(1); return *this; } _Rope_const_iterator& operator+=(ptrdiff_t __n) { if (__n >= 0) this->_M_incr(__n); else this->_M_decr(-__n); return *this; } _Rope_const_iterator& operator--() { this->_M_decr(1); return *this; } _Rope_const_iterator& operator-=(ptrdiff_t __n) { if (__n >= 0) this->_M_decr(__n); else this->_M_incr(-__n); return *this; } _Rope_const_iterator operator++(int) { size_t __old_pos = this->_M_current_pos; this->_M_incr(1); return _Rope_const_iterator<_CharT,_Alloc>(this->_M_root, __old_pos); // This makes a subsequent dereference expensive. // Perhaps we should instead copy the iterator // if it has a valid cache? } _Rope_const_iterator operator--(int) { size_t __old_pos = this->_M_current_pos; this->_M_decr(1); return _Rope_const_iterator<_CharT,_Alloc>(this->_M_root, __old_pos); } template friend _Rope_const_iterator<_CharT2, _Alloc2> operator-(const _Rope_const_iterator<_CharT2, _Alloc2>& __x, ptrdiff_t __n); template friend _Rope_const_iterator<_CharT2, _Alloc2> operator+(const _Rope_const_iterator<_CharT2, _Alloc2>& __x, ptrdiff_t __n); template friend _Rope_const_iterator<_CharT2, _Alloc2> operator+(ptrdiff_t __n, const _Rope_const_iterator<_CharT2, _Alloc2>& __x); reference operator[](size_t __n) { return rope<_CharT, _Alloc>::_S_fetch(this->_M_root, this->_M_current_pos + __n); } template friend bool operator==(const _Rope_const_iterator<_CharT2, _Alloc2>& __x, const _Rope_const_iterator<_CharT2, _Alloc2>& __y); template friend bool operator<(const _Rope_const_iterator<_CharT2, _Alloc2>& __x, const _Rope_const_iterator<_CharT2, _Alloc2>& __y); template friend ptrdiff_t operator-(const _Rope_const_iterator<_CharT2, _Alloc2>& __x, const _Rope_const_iterator<_CharT2, _Alloc2>& __y); }; template class _Rope_iterator : public _Rope_iterator_base<_CharT, _Alloc> { friend class rope<_CharT, _Alloc>; protected: typedef typename _Rope_iterator_base<_CharT, _Alloc>::_RopeRep _RopeRep; rope<_CharT, _Alloc>* _M_root_rope; // root is treated as a cached version of this, and is used to // detect changes to the underlying rope. // Root is included in the reference count. This is necessary // so that we can detect changes reliably. Unfortunately, it // requires careful bookkeeping for the nonGC case. _Rope_iterator(rope<_CharT, _Alloc>* __r, size_t __pos) : _Rope_iterator_base<_CharT, _Alloc>(__r->_M_tree_ptr, __pos), _M_root_rope(__r) { _RopeRep::_S_ref(this->_M_root); if (!(__r -> empty())) this->_S_setcache(*this); } void _M_check(); public: typedef _Rope_char_ref_proxy<_CharT, _Alloc> reference; typedef _Rope_char_ref_proxy<_CharT, _Alloc>* pointer; rope<_CharT, _Alloc>& container() { return *_M_root_rope; } _Rope_iterator() { this->_M_root = 0; // Needed for reference counting. } _Rope_iterator(const _Rope_iterator& __x) : _Rope_iterator_base<_CharT, _Alloc>(__x) { _M_root_rope = __x._M_root_rope; _RopeRep::_S_ref(this->_M_root); } _Rope_iterator(rope<_CharT, _Alloc>& __r, size_t __pos); ~_Rope_iterator() { _RopeRep::_S_unref(this->_M_root); } _Rope_iterator& operator=(const _Rope_iterator& __x) { _RopeRep* __old = this->_M_root; _RopeRep::_S_ref(__x._M_root); if (0 != __x._M_buf_ptr) { _M_root_rope = __x._M_root_rope; *(static_cast<_Rope_iterator_base<_CharT, _Alloc>*>(this)) = __x; } else { this->_M_current_pos = __x._M_current_pos; this->_M_root = __x._M_root; _M_root_rope = __x._M_root_rope; this->_M_buf_ptr = 0; } _RopeRep::_S_unref(__old); return(*this); } reference operator*() { _M_check(); if (0 == this->_M_buf_ptr) return _Rope_char_ref_proxy<_CharT, _Alloc>(_M_root_rope, this->_M_current_pos); else return _Rope_char_ref_proxy<_CharT, _Alloc>(_M_root_rope, this->_M_current_pos, *this->_M_buf_ptr); } // See above comment. reference operator*() const { return *const_cast<_Rope_iterator&>(*this); } _Rope_iterator& operator++() { this->_M_incr(1); return *this; } _Rope_iterator& operator+=(ptrdiff_t __n) { if (__n >= 0) this->_M_incr(__n); else this->_M_decr(-__n); return *this; } _Rope_iterator& operator--() { this->_M_decr(1); return *this; } _Rope_iterator& operator-=(ptrdiff_t __n) { if (__n >= 0) this->_M_decr(__n); else this->_M_incr(-__n); return *this; } _Rope_iterator operator++(int) { size_t __old_pos = this->_M_current_pos; this->_M_incr(1); return _Rope_iterator<_CharT,_Alloc>(_M_root_rope, __old_pos); } _Rope_iterator operator--(int) { size_t __old_pos = this->_M_current_pos; this->_M_decr(1); return _Rope_iterator<_CharT,_Alloc>(_M_root_rope, __old_pos); } reference operator[](ptrdiff_t __n) { return _Rope_char_ref_proxy<_CharT, _Alloc>(_M_root_rope, this->_M_current_pos + __n); } template friend bool operator==(const _Rope_iterator<_CharT2, _Alloc2>& __x, const _Rope_iterator<_CharT2, _Alloc2>& __y); template friend bool operator<(const _Rope_iterator<_CharT2, _Alloc2>& __x, const _Rope_iterator<_CharT2, _Alloc2>& __y); template friend ptrdiff_t operator-(const _Rope_iterator<_CharT2, _Alloc2>& __x, const _Rope_iterator<_CharT2, _Alloc2>& __y); template friend _Rope_iterator<_CharT2, _Alloc2> operator-(const _Rope_iterator<_CharT2, _Alloc2>& __x, ptrdiff_t __n); template friend _Rope_iterator<_CharT2, _Alloc2> operator+(const _Rope_iterator<_CharT2, _Alloc2>& __x, ptrdiff_t __n); template friend _Rope_iterator<_CharT2, _Alloc2> operator+(ptrdiff_t __n, const _Rope_iterator<_CharT2, _Alloc2>& __x); }; template struct _Rope_base : public _Alloc { typedef _Alloc allocator_type; allocator_type get_allocator() const { return *static_cast(this); } allocator_type& _M_get_allocator() { return *static_cast<_Alloc*>(this); } const allocator_type& _M_get_allocator() const { return *static_cast(this); } typedef _Rope_RopeRep<_CharT, _Alloc> _RopeRep; // The one in _Base may not be visible due to template rules. _Rope_base(_RopeRep* __t, const allocator_type&) : _M_tree_ptr(__t) { } _Rope_base(const allocator_type&) { } // The only data member of a rope: _RopeRep *_M_tree_ptr; #define __ROPE_DEFINE_ALLOC(_Tp, __name) \ typedef typename \ _Alloc::template rebind<_Tp>::other __name##Alloc; \ static _Tp* __name##_allocate(size_t __n) \ { return __name##Alloc().allocate(__n); } \ static void __name##_deallocate(_Tp *__p, size_t __n) \ { __name##Alloc().deallocate(__p, __n); } __ROPE_DEFINE_ALLOCS(_Alloc) #undef __ROPE_DEFINE_ALLOC protected: _Rope_base& operator=(const _Rope_base&); _Rope_base(const _Rope_base&); }; /** * This is an SGI extension. * @ingroup SGIextensions * @doctodo */ template class rope : public _Rope_base<_CharT, _Alloc> { public: typedef _CharT value_type; typedef ptrdiff_t difference_type; typedef size_t size_type; typedef _CharT const_reference; typedef const _CharT* const_pointer; typedef _Rope_iterator<_CharT, _Alloc> iterator; typedef _Rope_const_iterator<_CharT, _Alloc> const_iterator; typedef _Rope_char_ref_proxy<_CharT, _Alloc> reference; typedef _Rope_char_ptr_proxy<_CharT, _Alloc> pointer; friend class _Rope_iterator<_CharT, _Alloc>; friend class _Rope_const_iterator<_CharT, _Alloc>; friend struct _Rope_RopeRep<_CharT, _Alloc>; friend class _Rope_iterator_base<_CharT, _Alloc>; friend class _Rope_char_ptr_proxy<_CharT, _Alloc>; friend class _Rope_char_ref_proxy<_CharT, _Alloc>; friend struct _Rope_RopeSubstring<_CharT, _Alloc>; protected: typedef _Rope_base<_CharT, _Alloc> _Base; typedef typename _Base::allocator_type allocator_type; using _Base::_M_tree_ptr; using _Base::get_allocator; using _Base::_M_get_allocator; typedef __GC_CONST _CharT* _Cstrptr; static _CharT _S_empty_c_str[1]; static bool _S_is0(_CharT __c) { return __c == _S_eos((_CharT*)0); } enum { _S_copy_max = 23 }; // For strings shorter than _S_copy_max, we copy to // concatenate. typedef _Rope_RopeRep<_CharT, _Alloc> _RopeRep; typedef _Rope_RopeConcatenation<_CharT, _Alloc> _RopeConcatenation; typedef _Rope_RopeLeaf<_CharT, _Alloc> _RopeLeaf; typedef _Rope_RopeFunction<_CharT, _Alloc> _RopeFunction; typedef _Rope_RopeSubstring<_CharT, _Alloc> _RopeSubstring; // Retrieve a character at the indicated position. static _CharT _S_fetch(_RopeRep* __r, size_type __pos); #ifndef __GC // Obtain a pointer to the character at the indicated position. // The pointer can be used to change the character. // If such a pointer cannot be produced, as is frequently the // case, 0 is returned instead. // (Returns nonzero only if all nodes in the path have a refcount // of 1.) static _CharT* _S_fetch_ptr(_RopeRep* __r, size_type __pos); #endif static bool _S_apply_to_pieces(// should be template parameter _Rope_char_consumer<_CharT>& __c, const _RopeRep* __r, size_t __begin, size_t __end); // begin and end are assumed to be in range. #ifndef __GC static void _S_unref(_RopeRep* __t) { _RopeRep::_S_unref(__t); } static void _S_ref(_RopeRep* __t) { _RopeRep::_S_ref(__t); } #else /* __GC */ static void _S_unref(_RopeRep*) { } static void _S_ref(_RopeRep*) { } #endif #ifdef __GC typedef _Rope_RopeRep<_CharT, _Alloc>* _Self_destruct_ptr; #else typedef _Rope_self_destruct_ptr<_CharT, _Alloc> _Self_destruct_ptr; #endif // _Result is counted in refcount. static _RopeRep* _S_substring(_RopeRep* __base, size_t __start, size_t __endp1); static _RopeRep* _S_concat_char_iter(_RopeRep* __r, const _CharT* __iter, size_t __slen); // Concatenate rope and char ptr, copying __s. // Should really take an arbitrary iterator. // Result is counted in refcount. static _RopeRep* _S_destr_concat_char_iter(_RopeRep* __r, const _CharT* __iter, size_t __slen) // As above, but one reference to __r is about to be // destroyed. Thus the pieces may be recycled if all // relevant reference counts are 1. #ifdef __GC // We can't really do anything since refcounts are unavailable. { return _S_concat_char_iter(__r, __iter, __slen); } #else ; #endif static _RopeRep* _S_concat(_RopeRep* __left, _RopeRep* __right); // General concatenation on _RopeRep. _Result // has refcount of 1. Adjusts argument refcounts. public: void apply_to_pieces(size_t __begin, size_t __end, _Rope_char_consumer<_CharT>& __c) const { _S_apply_to_pieces(__c, this->_M_tree_ptr, __begin, __end); } protected: static size_t _S_rounded_up_size(size_t __n) { return _RopeLeaf::_S_rounded_up_size(__n); } static size_t _S_allocated_capacity(size_t __n) { if (_S_is_basic_char_type((_CharT*)0)) return _S_rounded_up_size(__n) - 1; else return _S_rounded_up_size(__n); } // Allocate and construct a RopeLeaf using the supplied allocator // Takes ownership of s instead of copying. static _RopeLeaf* _S_new_RopeLeaf(__GC_CONST _CharT *__s, size_t __size, allocator_type& __a) { _RopeLeaf* __space = typename _Base::_LAlloc(__a).allocate(1); return new(__space) _RopeLeaf(__s, __size, __a); } static _RopeConcatenation* _S_new_RopeConcatenation(_RopeRep* __left, _RopeRep* __right, allocator_type& __a) { _RopeConcatenation* __space = typename _Base::_CAlloc(__a).allocate(1); return new(__space) _RopeConcatenation(__left, __right, __a); } static _RopeFunction* _S_new_RopeFunction(char_producer<_CharT>* __f, size_t __size, bool __d, allocator_type& __a) { _RopeFunction* __space = typename _Base::_FAlloc(__a).allocate(1); return new(__space) _RopeFunction(__f, __size, __d, __a); } static _RopeSubstring* _S_new_RopeSubstring(_Rope_RopeRep<_CharT,_Alloc>* __b, size_t __s, size_t __l, allocator_type& __a) { _RopeSubstring* __space = typename _Base::_SAlloc(__a).allocate(1); return new(__space) _RopeSubstring(__b, __s, __l, __a); } static _RopeLeaf* _S_RopeLeaf_from_unowned_char_ptr(const _CharT *__s, size_t __size, allocator_type& __a) #define __STL_ROPE_FROM_UNOWNED_CHAR_PTR(__s, __size, __a) \ _S_RopeLeaf_from_unowned_char_ptr(__s, __size, __a) { if (0 == __size) return 0; _CharT* __buf = __a.allocate(_S_rounded_up_size(__size)); __uninitialized_copy_n_a(__s, __size, __buf, __a); _S_cond_store_eos(__buf[__size]); __try { return _S_new_RopeLeaf(__buf, __size, __a); } __catch(...) { _RopeRep::__STL_FREE_STRING(__buf, __size, __a); __throw_exception_again; } } // Concatenation of nonempty strings. // Always builds a concatenation node. // Rebalances if the result is too deep. // Result has refcount 1. // Does not increment left and right ref counts even though // they are referenced. static _RopeRep* _S_tree_concat(_RopeRep* __left, _RopeRep* __right); // Concatenation helper functions static _RopeLeaf* _S_leaf_concat_char_iter(_RopeLeaf* __r, const _CharT* __iter, size_t __slen); // Concatenate by copying leaf. // should take an arbitrary iterator // result has refcount 1. #ifndef __GC static _RopeLeaf* _S_destr_leaf_concat_char_iter(_RopeLeaf* __r, const _CharT* __iter, size_t __slen); // A version that potentially clobbers __r if __r->_M_ref_count == 1. #endif private: static size_t _S_char_ptr_len(const _CharT* __s); // slightly generalized strlen rope(_RopeRep* __t, const allocator_type& __a = allocator_type()) : _Base(__t, __a) { } // Copy __r to the _CharT buffer. // Returns __buffer + __r->_M_size. // Assumes that buffer is uninitialized. static _CharT* _S_flatten(_RopeRep* __r, _CharT* __buffer); // Again, with explicit starting position and length. // Assumes that buffer is uninitialized. static _CharT* _S_flatten(_RopeRep* __r, size_t __start, size_t __len, _CharT* __buffer); static const unsigned long _S_min_len[__detail::_S_max_rope_depth + 1]; static bool _S_is_balanced(_RopeRep* __r) { return (__r->_M_size >= _S_min_len[__r->_M_depth]); } static bool _S_is_almost_balanced(_RopeRep* __r) { return (__r->_M_depth == 0 || __r->_M_size >= _S_min_len[__r->_M_depth - 1]); } static bool _S_is_roughly_balanced(_RopeRep* __r) { return (__r->_M_depth <= 1 || __r->_M_size >= _S_min_len[__r->_M_depth - 2]); } // Assumes the result is not empty. static _RopeRep* _S_concat_and_set_balanced(_RopeRep* __left, _RopeRep* __right) { _RopeRep* __result = _S_concat(__left, __right); if (_S_is_balanced(__result)) __result->_M_is_balanced = true; return __result; } // The basic rebalancing operation. Logically copies the // rope. The result has refcount of 1. The client will // usually decrement the reference count of __r. // The result is within height 2 of balanced by the above // definition. static _RopeRep* _S_balance(_RopeRep* __r); // Add all unbalanced subtrees to the forest of balanced trees. // Used only by balance. static void _S_add_to_forest(_RopeRep*__r, _RopeRep** __forest); // Add __r to forest, assuming __r is already balanced. static void _S_add_leaf_to_forest(_RopeRep* __r, _RopeRep** __forest); // Print to stdout, exposing structure static void _S_dump(_RopeRep* __r, int __indent = 0); // Return -1, 0, or 1 if __x < __y, __x == __y, or __x > __y resp. static int _S_compare(const _RopeRep* __x, const _RopeRep* __y); public: bool empty() const { return 0 == this->_M_tree_ptr; } // Comparison member function. This is public only for those // clients that need a ternary comparison. Others // should use the comparison operators below. int compare(const rope& __y) const { return _S_compare(this->_M_tree_ptr, __y._M_tree_ptr); } rope(const _CharT* __s, const allocator_type& __a = allocator_type()) : _Base(__a) { this->_M_tree_ptr = __STL_ROPE_FROM_UNOWNED_CHAR_PTR(__s, _S_char_ptr_len(__s), _M_get_allocator()); } rope(const _CharT* __s, size_t __len, const allocator_type& __a = allocator_type()) : _Base(__a) { this->_M_tree_ptr = __STL_ROPE_FROM_UNOWNED_CHAR_PTR(__s, __len, _M_get_allocator()); } // Should perhaps be templatized with respect to the iterator type // and use Sequence_buffer. (It should perhaps use sequence_buffer // even now.) rope(const _CharT* __s, const _CharT* __e, const allocator_type& __a = allocator_type()) : _Base(__a) { this->_M_tree_ptr = __STL_ROPE_FROM_UNOWNED_CHAR_PTR(__s, __e - __s, _M_get_allocator()); } rope(const const_iterator& __s, const const_iterator& __e, const allocator_type& __a = allocator_type()) : _Base(_S_substring(__s._M_root, __s._M_current_pos, __e._M_current_pos), __a) { } rope(const iterator& __s, const iterator& __e, const allocator_type& __a = allocator_type()) : _Base(_S_substring(__s._M_root, __s._M_current_pos, __e._M_current_pos), __a) { } rope(_CharT __c, const allocator_type& __a = allocator_type()) : _Base(__a) { _CharT* __buf = this->_Data_allocate(_S_rounded_up_size(1)); _M_get_allocator().construct(__buf, __c); __try { this->_M_tree_ptr = _S_new_RopeLeaf(__buf, 1, _M_get_allocator()); } __catch(...) { _RopeRep::__STL_FREE_STRING(__buf, 1, _M_get_allocator()); __throw_exception_again; } } rope(size_t __n, _CharT __c, const allocator_type& __a = allocator_type()); rope(const allocator_type& __a = allocator_type()) : _Base(0, __a) { } // Construct a rope from a function that can compute its members rope(char_producer<_CharT> *__fn, size_t __len, bool __delete_fn, const allocator_type& __a = allocator_type()) : _Base(__a) { this->_M_tree_ptr = (0 == __len) ? 0 : _S_new_RopeFunction(__fn, __len, __delete_fn, _M_get_allocator()); } rope(const rope& __x, const allocator_type& __a = allocator_type()) : _Base(__x._M_tree_ptr, __a) { _S_ref(this->_M_tree_ptr); } ~rope() throw() { _S_unref(this->_M_tree_ptr); } rope& operator=(const rope& __x) { _RopeRep* __old = this->_M_tree_ptr; this->_M_tree_ptr = __x._M_tree_ptr; _S_ref(this->_M_tree_ptr); _S_unref(__old); return *this; } void clear() { _S_unref(this->_M_tree_ptr); this->_M_tree_ptr = 0; } void push_back(_CharT __x) { _RopeRep* __old = this->_M_tree_ptr; this->_M_tree_ptr = _S_destr_concat_char_iter(this->_M_tree_ptr, &__x, 1); _S_unref(__old); } void pop_back() { _RopeRep* __old = this->_M_tree_ptr; this->_M_tree_ptr = _S_substring(this->_M_tree_ptr, 0, this->_M_tree_ptr->_M_size - 1); _S_unref(__old); } _CharT back() const { return _S_fetch(this->_M_tree_ptr, this->_M_tree_ptr->_M_size - 1); } void push_front(_CharT __x) { _RopeRep* __old = this->_M_tree_ptr; _RopeRep* __left = __STL_ROPE_FROM_UNOWNED_CHAR_PTR(&__x, 1, _M_get_allocator()); __try { this->_M_tree_ptr = _S_concat(__left, this->_M_tree_ptr); _S_unref(__old); _S_unref(__left); } __catch(...) { _S_unref(__left); __throw_exception_again; } } void pop_front() { _RopeRep* __old = this->_M_tree_ptr; this->_M_tree_ptr = _S_substring(this->_M_tree_ptr, 1, this->_M_tree_ptr->_M_size); _S_unref(__old); } _CharT front() const { return _S_fetch(this->_M_tree_ptr, 0); } void balance() { _RopeRep* __old = this->_M_tree_ptr; this->_M_tree_ptr = _S_balance(this->_M_tree_ptr); _S_unref(__old); } void copy(_CharT* __buffer) const { _Destroy_const(__buffer, __buffer + size(), _M_get_allocator()); _S_flatten(this->_M_tree_ptr, __buffer); } // This is the copy function from the standard, but // with the arguments reordered to make it consistent with the // rest of the interface. // Note that this guaranteed not to compile if the draft standard // order is assumed. size_type copy(size_type __pos, size_type __n, _CharT* __buffer) const { size_t __size = size(); size_t __len = (__pos + __n > __size? __size - __pos : __n); _Destroy_const(__buffer, __buffer + __len, _M_get_allocator()); _S_flatten(this->_M_tree_ptr, __pos, __len, __buffer); return __len; } // Print to stdout, exposing structure. May be useful for // performance debugging. void dump() { _S_dump(this->_M_tree_ptr); } // Convert to 0 terminated string in new allocated memory. // Embedded 0s in the input do not terminate the copy. const _CharT* c_str() const; // As above, but also use the flattened representation as // the new rope representation. const _CharT* replace_with_c_str(); // Reclaim memory for the c_str generated flattened string. // Intentionally undocumented, since it's hard to say when this // is safe for multiple threads. void delete_c_str () { if (0 == this->_M_tree_ptr) return; if (__detail::_S_leaf == this->_M_tree_ptr->_M_tag && ((_RopeLeaf*)this->_M_tree_ptr)->_M_data == this->_M_tree_ptr->_M_c_string) { // Representation shared return; } #ifndef __GC this->_M_tree_ptr->_M_free_c_string(); #endif this->_M_tree_ptr->_M_c_string = 0; } _CharT operator[] (size_type __pos) const { return _S_fetch(this->_M_tree_ptr, __pos); } _CharT at(size_type __pos) const { // if (__pos >= size()) throw out_of_range; // XXX return (*this)[__pos]; } const_iterator begin() const { return(const_iterator(this->_M_tree_ptr, 0)); } // An easy way to get a const iterator from a non-const container. const_iterator const_begin() const { return(const_iterator(this->_M_tree_ptr, 0)); } const_iterator end() const { return(const_iterator(this->_M_tree_ptr, size())); } const_iterator const_end() const { return(const_iterator(this->_M_tree_ptr, size())); } size_type size() const { return(0 == this->_M_tree_ptr? 0 : this->_M_tree_ptr->_M_size); } size_type length() const { return size(); } size_type max_size() const { return _S_min_len[int(__detail::_S_max_rope_depth) - 1] - 1; // Guarantees that the result can be sufficiently // balanced. Longer ropes will probably still work, // but it's harder to make guarantees. } typedef std::reverse_iterator const_reverse_iterator; const_reverse_iterator rbegin() const { return const_reverse_iterator(end()); } const_reverse_iterator const_rbegin() const { return const_reverse_iterator(end()); } const_reverse_iterator rend() const { return const_reverse_iterator(begin()); } const_reverse_iterator const_rend() const { return const_reverse_iterator(begin()); } template friend rope<_CharT2, _Alloc2> operator+(const rope<_CharT2, _Alloc2>& __left, const rope<_CharT2, _Alloc2>& __right); template friend rope<_CharT2, _Alloc2> operator+(const rope<_CharT2, _Alloc2>& __left, const _CharT2* __right); template friend rope<_CharT2, _Alloc2> operator+(const rope<_CharT2, _Alloc2>& __left, _CharT2 __right); // The symmetric cases are intentionally omitted, since they're // presumed to be less common, and we don't handle them as well. // The following should really be templatized. The first // argument should be an input iterator or forward iterator with // value_type _CharT. rope& append(const _CharT* __iter, size_t __n) { _RopeRep* __result = _S_destr_concat_char_iter(this->_M_tree_ptr, __iter, __n); _S_unref(this->_M_tree_ptr); this->_M_tree_ptr = __result; return *this; } rope& append(const _CharT* __c_string) { size_t __len = _S_char_ptr_len(__c_string); append(__c_string, __len); return(*this); } rope& append(const _CharT* __s, const _CharT* __e) { _RopeRep* __result = _S_destr_concat_char_iter(this->_M_tree_ptr, __s, __e - __s); _S_unref(this->_M_tree_ptr); this->_M_tree_ptr = __result; return *this; } rope& append(const_iterator __s, const_iterator __e) { _Self_destruct_ptr __appendee(_S_substring(__s._M_root, __s._M_current_pos, __e._M_current_pos)); _RopeRep* __result = _S_concat(this->_M_tree_ptr, (_RopeRep*)__appendee); _S_unref(this->_M_tree_ptr); this->_M_tree_ptr = __result; return *this; } rope& append(_CharT __c) { _RopeRep* __result = _S_destr_concat_char_iter(this->_M_tree_ptr, &__c, 1); _S_unref(this->_M_tree_ptr); this->_M_tree_ptr = __result; return *this; } rope& append() { return append(_CharT()); } // XXX why? rope& append(const rope& __y) { _RopeRep* __result = _S_concat(this->_M_tree_ptr, __y._M_tree_ptr); _S_unref(this->_M_tree_ptr); this->_M_tree_ptr = __result; return *this; } rope& append(size_t __n, _CharT __c) { rope<_CharT,_Alloc> __last(__n, __c); return append(__last); } void swap(rope& __b) { _RopeRep* __tmp = this->_M_tree_ptr; this->_M_tree_ptr = __b._M_tree_ptr; __b._M_tree_ptr = __tmp; } protected: // Result is included in refcount. static _RopeRep* replace(_RopeRep* __old, size_t __pos1, size_t __pos2, _RopeRep* __r) { if (0 == __old) { _S_ref(__r); return __r; } _Self_destruct_ptr __left(_S_substring(__old, 0, __pos1)); _Self_destruct_ptr __right(_S_substring(__old, __pos2, __old->_M_size)); _RopeRep* __result; if (0 == __r) __result = _S_concat(__left, __right); else { _Self_destruct_ptr __left_result(_S_concat(__left, __r)); __result = _S_concat(__left_result, __right); } return __result; } public: void insert(size_t __p, const rope& __r) { _RopeRep* __result = replace(this->_M_tree_ptr, __p, __p, __r._M_tree_ptr); _S_unref(this->_M_tree_ptr); this->_M_tree_ptr = __result; } void insert(size_t __p, size_t __n, _CharT __c) { rope<_CharT,_Alloc> __r(__n,__c); insert(__p, __r); } void insert(size_t __p, const _CharT* __i, size_t __n) { _Self_destruct_ptr __left(_S_substring(this->_M_tree_ptr, 0, __p)); _Self_destruct_ptr __right(_S_substring(this->_M_tree_ptr, __p, size())); _Self_destruct_ptr __left_result(_S_concat_char_iter(__left, __i, __n)); // _S_ destr_concat_char_iter should be safe here. // But as it stands it's probably not a win, since __left // is likely to have additional references. _RopeRep* __result = _S_concat(__left_result, __right); _S_unref(this->_M_tree_ptr); this->_M_tree_ptr = __result; } void insert(size_t __p, const _CharT* __c_string) { insert(__p, __c_string, _S_char_ptr_len(__c_string)); } void insert(size_t __p, _CharT __c) { insert(__p, &__c, 1); } void insert(size_t __p) { _CharT __c = _CharT(); insert(__p, &__c, 1); } void insert(size_t __p, const _CharT* __i, const _CharT* __j) { rope __r(__i, __j); insert(__p, __r); } void insert(size_t __p, const const_iterator& __i, const const_iterator& __j) { rope __r(__i, __j); insert(__p, __r); } void insert(size_t __p, const iterator& __i, const iterator& __j) { rope __r(__i, __j); insert(__p, __r); } // (position, length) versions of replace operations: void replace(size_t __p, size_t __n, const rope& __r) { _RopeRep* __result = replace(this->_M_tree_ptr, __p, __p + __n, __r._M_tree_ptr); _S_unref(this->_M_tree_ptr); this->_M_tree_ptr = __result; } void replace(size_t __p, size_t __n, const _CharT* __i, size_t __i_len) { rope __r(__i, __i_len); replace(__p, __n, __r); } void replace(size_t __p, size_t __n, _CharT __c) { rope __r(__c); replace(__p, __n, __r); } void replace(size_t __p, size_t __n, const _CharT* __c_string) { rope __r(__c_string); replace(__p, __n, __r); } void replace(size_t __p, size_t __n, const _CharT* __i, const _CharT* __j) { rope __r(__i, __j); replace(__p, __n, __r); } void replace(size_t __p, size_t __n, const const_iterator& __i, const const_iterator& __j) { rope __r(__i, __j); replace(__p, __n, __r); } void replace(size_t __p, size_t __n, const iterator& __i, const iterator& __j) { rope __r(__i, __j); replace(__p, __n, __r); } // Single character variants: void replace(size_t __p, _CharT __c) { iterator __i(this, __p); *__i = __c; } void replace(size_t __p, const rope& __r) { replace(__p, 1, __r); } void replace(size_t __p, const _CharT* __i, size_t __i_len) { replace(__p, 1, __i, __i_len); } void replace(size_t __p, const _CharT* __c_string) { replace(__p, 1, __c_string); } void replace(size_t __p, const _CharT* __i, const _CharT* __j) { replace(__p, 1, __i, __j); } void replace(size_t __p, const const_iterator& __i, const const_iterator& __j) { replace(__p, 1, __i, __j); } void replace(size_t __p, const iterator& __i, const iterator& __j) { replace(__p, 1, __i, __j); } // Erase, (position, size) variant. void erase(size_t __p, size_t __n) { _RopeRep* __result = replace(this->_M_tree_ptr, __p, __p + __n, 0); _S_unref(this->_M_tree_ptr); this->_M_tree_ptr = __result; } // Erase, single character void erase(size_t __p) { erase(__p, __p + 1); } // Insert, iterator variants. iterator insert(const iterator& __p, const rope& __r) { insert(__p.index(), __r); return __p; } iterator insert(const iterator& __p, size_t __n, _CharT __c) { insert(__p.index(), __n, __c); return __p; } iterator insert(const iterator& __p, _CharT __c) { insert(__p.index(), __c); return __p; } iterator insert(const iterator& __p ) { insert(__p.index()); return __p; } iterator insert(const iterator& __p, const _CharT* c_string) { insert(__p.index(), c_string); return __p; } iterator insert(const iterator& __p, const _CharT* __i, size_t __n) { insert(__p.index(), __i, __n); return __p; } iterator insert(const iterator& __p, const _CharT* __i, const _CharT* __j) { insert(__p.index(), __i, __j); return __p; } iterator insert(const iterator& __p, const const_iterator& __i, const const_iterator& __j) { insert(__p.index(), __i, __j); return __p; } iterator insert(const iterator& __p, const iterator& __i, const iterator& __j) { insert(__p.index(), __i, __j); return __p; } // Replace, range variants. void replace(const iterator& __p, const iterator& __q, const rope& __r) { replace(__p.index(), __q.index() - __p.index(), __r); } void replace(const iterator& __p, const iterator& __q, _CharT __c) { replace(__p.index(), __q.index() - __p.index(), __c); } void replace(const iterator& __p, const iterator& __q, const _CharT* __c_string) { replace(__p.index(), __q.index() - __p.index(), __c_string); } void replace(const iterator& __p, const iterator& __q, const _CharT* __i, size_t __n) { replace(__p.index(), __q.index() - __p.index(), __i, __n); } void replace(const iterator& __p, const iterator& __q, const _CharT* __i, const _CharT* __j) { replace(__p.index(), __q.index() - __p.index(), __i, __j); } void replace(const iterator& __p, const iterator& __q, const const_iterator& __i, const const_iterator& __j) { replace(__p.index(), __q.index() - __p.index(), __i, __j); } void replace(const iterator& __p, const iterator& __q, const iterator& __i, const iterator& __j) { replace(__p.index(), __q.index() - __p.index(), __i, __j); } // Replace, iterator variants. void replace(const iterator& __p, const rope& __r) { replace(__p.index(), __r); } void replace(const iterator& __p, _CharT __c) { replace(__p.index(), __c); } void replace(const iterator& __p, const _CharT* __c_string) { replace(__p.index(), __c_string); } void replace(const iterator& __p, const _CharT* __i, size_t __n) { replace(__p.index(), __i, __n); } void replace(const iterator& __p, const _CharT* __i, const _CharT* __j) { replace(__p.index(), __i, __j); } void replace(const iterator& __p, const_iterator __i, const_iterator __j) { replace(__p.index(), __i, __j); } void replace(const iterator& __p, iterator __i, iterator __j) { replace(__p.index(), __i, __j); } // Iterator and range variants of erase iterator erase(const iterator& __p, const iterator& __q) { size_t __p_index = __p.index(); erase(__p_index, __q.index() - __p_index); return iterator(this, __p_index); } iterator erase(const iterator& __p) { size_t __p_index = __p.index(); erase(__p_index, 1); return iterator(this, __p_index); } rope substr(size_t __start, size_t __len = 1) const { return rope<_CharT, _Alloc>(_S_substring(this->_M_tree_ptr, __start, __start + __len)); } rope substr(iterator __start, iterator __end) const { return rope<_CharT, _Alloc>(_S_substring(this->_M_tree_ptr, __start.index(), __end.index())); } rope substr(iterator __start) const { size_t __pos = __start.index(); return rope<_CharT, _Alloc>(_S_substring(this->_M_tree_ptr, __pos, __pos + 1)); } rope substr(const_iterator __start, const_iterator __end) const { // This might eventually take advantage of the cache in the // iterator. return rope<_CharT, _Alloc>(_S_substring(this->_M_tree_ptr, __start.index(), __end.index())); } rope<_CharT, _Alloc> substr(const_iterator __start) { size_t __pos = __start.index(); return rope<_CharT, _Alloc>(_S_substring(this->_M_tree_ptr, __pos, __pos + 1)); } static const size_type npos; size_type find(_CharT __c, size_type __pos = 0) const; size_type find(const _CharT* __s, size_type __pos = 0) const { size_type __result_pos; const_iterator __result = std::search(const_begin() + __pos, const_end(), __s, __s + _S_char_ptr_len(__s)); __result_pos = __result.index(); #ifndef __STL_OLD_ROPE_SEMANTICS if (__result_pos == size()) __result_pos = npos; #endif return __result_pos; } iterator mutable_begin() { return(iterator(this, 0)); } iterator mutable_end() { return(iterator(this, size())); } typedef std::reverse_iterator reverse_iterator; reverse_iterator mutable_rbegin() { return reverse_iterator(mutable_end()); } reverse_iterator mutable_rend() { return reverse_iterator(mutable_begin()); } reference mutable_reference_at(size_type __pos) { return reference(this, __pos); } #ifdef __STD_STUFF reference operator[] (size_type __pos) { return _char_ref_proxy(this, __pos); } reference at(size_type __pos) { // if (__pos >= size()) throw out_of_range; // XXX return (*this)[__pos]; } void resize(size_type __n, _CharT __c) { } void resize(size_type __n) { } void reserve(size_type __res_arg = 0) { } size_type capacity() const { return max_size(); } // Stuff below this line is dangerous because it's error prone. // I would really like to get rid of it. // copy function with funny arg ordering. size_type copy(_CharT* __buffer, size_type __n, size_type __pos = 0) const { return copy(__pos, __n, __buffer); } iterator end() { return mutable_end(); } iterator begin() { return mutable_begin(); } reverse_iterator rend() { return mutable_rend(); } reverse_iterator rbegin() { return mutable_rbegin(); } #else const_iterator end() { return const_end(); } const_iterator begin() { return const_begin(); } const_reverse_iterator rend() { return const_rend(); } const_reverse_iterator rbegin() { return const_rbegin(); } #endif }; template const typename rope<_CharT, _Alloc>::size_type rope<_CharT, _Alloc>::npos = (size_type)(-1); template inline bool operator==(const _Rope_const_iterator<_CharT, _Alloc>& __x, const _Rope_const_iterator<_CharT, _Alloc>& __y) { return (__x._M_current_pos == __y._M_current_pos && __x._M_root == __y._M_root); } template inline bool operator<(const _Rope_const_iterator<_CharT, _Alloc>& __x, const _Rope_const_iterator<_CharT, _Alloc>& __y) { return (__x._M_current_pos < __y._M_current_pos); } template inline bool operator!=(const _Rope_const_iterator<_CharT, _Alloc>& __x, const _Rope_const_iterator<_CharT, _Alloc>& __y) { return !(__x == __y); } template inline bool operator>(const _Rope_const_iterator<_CharT, _Alloc>& __x, const _Rope_const_iterator<_CharT, _Alloc>& __y) { return __y < __x; } template inline bool operator<=(const _Rope_const_iterator<_CharT, _Alloc>& __x, const _Rope_const_iterator<_CharT, _Alloc>& __y) { return !(__y < __x); } template inline bool operator>=(const _Rope_const_iterator<_CharT, _Alloc>& __x, const _Rope_const_iterator<_CharT, _Alloc>& __y) { return !(__x < __y); } template inline ptrdiff_t operator-(const _Rope_const_iterator<_CharT, _Alloc>& __x, const _Rope_const_iterator<_CharT, _Alloc>& __y) { return (ptrdiff_t)__x._M_current_pos - (ptrdiff_t)__y._M_current_pos; } template inline _Rope_const_iterator<_CharT, _Alloc> operator-(const _Rope_const_iterator<_CharT, _Alloc>& __x, ptrdiff_t __n) { return _Rope_const_iterator<_CharT, _Alloc>(__x._M_root, __x._M_current_pos - __n); } template inline _Rope_const_iterator<_CharT, _Alloc> operator+(const _Rope_const_iterator<_CharT, _Alloc>& __x, ptrdiff_t __n) { return _Rope_const_iterator<_CharT, _Alloc>(__x._M_root, __x._M_current_pos + __n); } template inline _Rope_const_iterator<_CharT, _Alloc> operator+(ptrdiff_t __n, const _Rope_const_iterator<_CharT, _Alloc>& __x) { return _Rope_const_iterator<_CharT, _Alloc>(__x._M_root, __x._M_current_pos + __n); } template inline bool operator==(const _Rope_iterator<_CharT, _Alloc>& __x, const _Rope_iterator<_CharT, _Alloc>& __y) {return (__x._M_current_pos == __y._M_current_pos && __x._M_root_rope == __y._M_root_rope); } template inline bool operator<(const _Rope_iterator<_CharT, _Alloc>& __x, const _Rope_iterator<_CharT, _Alloc>& __y) { return (__x._M_current_pos < __y._M_current_pos); } template inline bool operator!=(const _Rope_iterator<_CharT, _Alloc>& __x, const _Rope_iterator<_CharT, _Alloc>& __y) { return !(__x == __y); } template inline bool operator>(const _Rope_iterator<_CharT, _Alloc>& __x, const _Rope_iterator<_CharT, _Alloc>& __y) { return __y < __x; } template inline bool operator<=(const _Rope_iterator<_CharT, _Alloc>& __x, const _Rope_iterator<_CharT, _Alloc>& __y) { return !(__y < __x); } template inline bool operator>=(const _Rope_iterator<_CharT, _Alloc>& __x, const _Rope_iterator<_CharT, _Alloc>& __y) { return !(__x < __y); } template inline ptrdiff_t operator-(const _Rope_iterator<_CharT, _Alloc>& __x, const _Rope_iterator<_CharT, _Alloc>& __y) { return ((ptrdiff_t)__x._M_current_pos - (ptrdiff_t)__y._M_current_pos); } template inline _Rope_iterator<_CharT, _Alloc> operator-(const _Rope_iterator<_CharT, _Alloc>& __x, ptrdiff_t __n) { return _Rope_iterator<_CharT, _Alloc>(__x._M_root_rope, __x._M_current_pos - __n); } template inline _Rope_iterator<_CharT, _Alloc> operator+(const _Rope_iterator<_CharT, _Alloc>& __x, ptrdiff_t __n) { return _Rope_iterator<_CharT, _Alloc>(__x._M_root_rope, __x._M_current_pos + __n); } template inline _Rope_iterator<_CharT, _Alloc> operator+(ptrdiff_t __n, const _Rope_iterator<_CharT, _Alloc>& __x) { return _Rope_iterator<_CharT, _Alloc>(__x._M_root_rope, __x._M_current_pos + __n); } template inline rope<_CharT, _Alloc> operator+(const rope<_CharT, _Alloc>& __left, const rope<_CharT, _Alloc>& __right) { // Inlining this should make it possible to keep __left and // __right in registers. typedef rope<_CharT, _Alloc> rope_type; return rope_type(rope_type::_S_concat(__left._M_tree_ptr, __right._M_tree_ptr)); } template inline rope<_CharT, _Alloc>& operator+=(rope<_CharT, _Alloc>& __left, const rope<_CharT, _Alloc>& __right) { __left.append(__right); return __left; } template inline rope<_CharT, _Alloc> operator+(const rope<_CharT, _Alloc>& __left, const _CharT* __right) { typedef rope<_CharT, _Alloc> rope_type; size_t __rlen = rope_type::_S_char_ptr_len(__right); return rope_type(rope_type::_S_concat_char_iter(__left._M_tree_ptr, __right, __rlen)); } template inline rope<_CharT, _Alloc>& operator+=(rope<_CharT, _Alloc>& __left, const _CharT* __right) { __left.append(__right); return __left; } template inline rope<_CharT, _Alloc> operator+(const rope<_CharT, _Alloc>& __left, _CharT __right) { typedef rope<_CharT, _Alloc> rope_type; return rope_type(rope_type::_S_concat_char_iter(__left._M_tree_ptr, &__right, 1)); } template inline rope<_CharT, _Alloc>& operator+=(rope<_CharT, _Alloc>& __left, _CharT __right) { __left.append(__right); return __left; } template bool operator<(const rope<_CharT, _Alloc>& __left, const rope<_CharT, _Alloc>& __right) { return __left.compare(__right) < 0; } template bool operator==(const rope<_CharT, _Alloc>& __left, const rope<_CharT, _Alloc>& __right) { return __left.compare(__right) == 0; } template inline bool operator==(const _Rope_char_ptr_proxy<_CharT, _Alloc>& __x, const _Rope_char_ptr_proxy<_CharT, _Alloc>& __y) { return (__x._M_pos == __y._M_pos && __x._M_root == __y._M_root); } template inline bool operator!=(const rope<_CharT, _Alloc>& __x, const rope<_CharT, _Alloc>& __y) { return !(__x == __y); } template inline bool operator>(const rope<_CharT, _Alloc>& __x, const rope<_CharT, _Alloc>& __y) { return __y < __x; } template inline bool operator<=(const rope<_CharT, _Alloc>& __x, const rope<_CharT, _Alloc>& __y) { return !(__y < __x); } template inline bool operator>=(const rope<_CharT, _Alloc>& __x, const rope<_CharT, _Alloc>& __y) { return !(__x < __y); } template inline bool operator!=(const _Rope_char_ptr_proxy<_CharT, _Alloc>& __x, const _Rope_char_ptr_proxy<_CharT, _Alloc>& __y) { return !(__x == __y); } template std::basic_ostream<_CharT, _Traits>& operator<<(std::basic_ostream<_CharT, _Traits>& __o, const rope<_CharT, _Alloc>& __r); typedef rope crope; typedef rope wrope; inline crope::reference __mutable_reference_at(crope& __c, size_t __i) { return __c.mutable_reference_at(__i); } inline wrope::reference __mutable_reference_at(wrope& __c, size_t __i) { return __c.mutable_reference_at(__i); } template inline void swap(rope<_CharT, _Alloc>& __x, rope<_CharT, _Alloc>& __y) { __x.swap(__y); } _GLIBCXX_END_NAMESPACE_VERSION } // namespace namespace std _GLIBCXX_VISIBILITY(default) { _GLIBCXX_BEGIN_NAMESPACE_VERSION namespace tr1 { template<> struct hash<__gnu_cxx::crope> { size_t operator()(const __gnu_cxx::crope& __str) const { size_t __size = __str.size(); if (0 == __size) return 0; return 13 * __str[0] + 5 * __str[__size - 1] + __size; } }; template<> struct hash<__gnu_cxx::wrope> { size_t operator()(const __gnu_cxx::wrope& __str) const { size_t __size = __str.size(); if (0 == __size) return 0; return 13 * __str[0] + 5 * __str[__size - 1] + __size; } }; } // namespace tr1 _GLIBCXX_END_NAMESPACE_VERSION } // namespace std # include #endif PKNd]}h  8/ext/array_allocator.hnu[// array allocator -*- C++ -*- // Copyright (C) 2004-2018 Free Software Foundation, Inc. // // This file is part of the GNU ISO C++ Library. This library is free // software; you can redistribute it and/or modify it under the // terms of the GNU General Public License as published by the // Free Software Foundation; either version 3, or (at your option) // any later version. // This library is distributed in the hope that it will be useful, // but WITHOUT ANY WARRANTY; without even the implied warranty of // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the // GNU General Public License for more details. // Under Section 7 of GPL version 3, you are granted additional // permissions described in the GCC Runtime Library Exception, version // 3.1, as published by the Free Software Foundation. // You should have received a copy of the GNU General Public License and // a copy of the GCC Runtime Library Exception along with this program; // see the files COPYING3 and COPYING.RUNTIME respectively. If not, see // . /** @file ext/array_allocator.h * This file is a GNU extension to the Standard C++ Library. */ #ifndef _ARRAY_ALLOCATOR_H #define _ARRAY_ALLOCATOR_H 1 #include #include #include #include #include #if __cplusplus >= 201103L #include #endif // Suppress deprecated warning for this file. #pragma GCC diagnostic push #pragma GCC diagnostic ignored "-Wdeprecated-declarations" namespace __gnu_cxx _GLIBCXX_VISIBILITY(default) { _GLIBCXX_BEGIN_NAMESPACE_VERSION using std::size_t; using std::ptrdiff_t; /// Base class. template class array_allocator_base { public: typedef size_t size_type; typedef ptrdiff_t difference_type; typedef _Tp* pointer; typedef const _Tp* const_pointer; typedef _Tp& reference; typedef const _Tp& const_reference; typedef _Tp value_type; pointer address(reference __x) const _GLIBCXX_NOEXCEPT { return std::__addressof(__x); } const_pointer address(const_reference __x) const _GLIBCXX_NOEXCEPT { return std::__addressof(__x); } void deallocate(pointer, size_type) { // Does nothing. } size_type max_size() const _GLIBCXX_USE_NOEXCEPT { return size_t(-1) / sizeof(_Tp); } #if __cplusplus >= 201103L template void construct(_Up* __p, _Args&&... __args) { ::new((void *)__p) _Up(std::forward<_Args>(__args)...); } template void destroy(_Up* __p) { __p->~_Up(); } #else // _GLIBCXX_RESOLVE_LIB_DEFECTS // 402. wrong new expression in [some_] allocator::construct void construct(pointer __p, const _Tp& __val) { ::new((void *)__p) value_type(__val); } void destroy(pointer __p) { __p->~_Tp(); } #endif } _GLIBCXX_DEPRECATED; /** * @brief An allocator that uses previously allocated memory. * This memory can be externally, globally, or otherwise allocated. * @ingroup allocators */ template > class array_allocator : public array_allocator_base<_Tp> { public: typedef size_t size_type; typedef ptrdiff_t difference_type; typedef _Tp* pointer; typedef const _Tp* const_pointer; typedef _Tp& reference; typedef const _Tp& const_reference; typedef _Tp value_type; typedef _Array array_type; #if __cplusplus >= 201103L // _GLIBCXX_RESOLVE_LIB_DEFECTS // 2103. std::allocator propagate_on_container_move_assignment typedef std::true_type propagate_on_container_move_assignment; typedef std::true_type is_always_equal; #endif private: array_type* _M_array; size_type _M_used; public: template struct rebind { typedef array_allocator<_Tp1, _Array1> other _GLIBCXX_DEPRECATED; } _GLIBCXX_DEPRECATED; array_allocator(array_type* __array = 0) _GLIBCXX_USE_NOEXCEPT : _M_array(__array), _M_used(size_type()) { } array_allocator(const array_allocator& __o) _GLIBCXX_USE_NOEXCEPT : _M_array(__o._M_array), _M_used(__o._M_used) { } template array_allocator(const array_allocator<_Tp1, _Array1>&) _GLIBCXX_USE_NOEXCEPT : _M_array(0), _M_used(size_type()) { } ~array_allocator() _GLIBCXX_USE_NOEXCEPT { } pointer allocate(size_type __n, const void* = 0) { if (_M_array == 0 || _M_used + __n > _M_array->size()) std::__throw_bad_alloc(); pointer __ret = _M_array->begin() + _M_used; _M_used += __n; return __ret; } } _GLIBCXX_DEPRECATED; template inline bool operator==(const array_allocator<_Tp, _Array>&, const array_allocator<_Tp, _Array>&) { return true; } template inline bool operator!=(const array_allocator<_Tp, _Array>&, const array_allocator<_Tp, _Array>&) { return false; } _GLIBCXX_END_NAMESPACE_VERSION } // namespace #pragma GCC diagnostic pop #endif PKNd]]'8/ext/enc_filebuf.hnu[// filebuf with encoding state type -*- C++ -*- // Copyright (C) 2002-2018 Free Software Foundation, Inc. // // This file is part of the GNU ISO C++ Library. This library is free // software; you can redistribute it and/or modify it under the // terms of the GNU General Public License as published by the // Free Software Foundation; either version 3, or (at your option) // any later version. // This library is distributed in the hope that it will be useful, // but WITHOUT ANY WARRANTY; without even the implied warranty of // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the // GNU General Public License for more details. // Under Section 7 of GPL version 3, you are granted additional // permissions described in the GCC Runtime Library Exception, version // 3.1, as published by the Free Software Foundation. // You should have received a copy of the GNU General Public License and // a copy of the GCC Runtime Library Exception along with this program; // see the files COPYING3 and COPYING.RUNTIME respectively. If not, see // . /** @file ext/enc_filebuf.h * This file is a GNU extension to the Standard C++ Library. */ #ifndef _EXT_ENC_FILEBUF_H #define _EXT_ENC_FILEBUF_H 1 #include #include #include namespace __gnu_cxx _GLIBCXX_VISIBILITY(default) { _GLIBCXX_BEGIN_NAMESPACE_VERSION /// class enc_filebuf. template class enc_filebuf : public std::basic_filebuf<_CharT, encoding_char_traits<_CharT> > { public: typedef encoding_char_traits<_CharT> traits_type; typedef typename traits_type::state_type state_type; typedef typename traits_type::pos_type pos_type; enc_filebuf(state_type& __state) : std::basic_filebuf<_CharT, encoding_char_traits<_CharT> >() { this->_M_state_beg = __state; } private: // concept requirements: // Set state type to something useful. // Something more than copyconstructible is needed here, so // require default and copy constructible + assignment operator. __glibcxx_class_requires(state_type, _SGIAssignableConcept) }; _GLIBCXX_END_NAMESPACE_VERSION } // namespace #endif PKNd]bȝ 8/ext/atomicity.hnu[// Support for atomic operations -*- C++ -*- // Copyright (C) 2004-2018 Free Software Foundation, Inc. // // This file is part of the GNU ISO C++ Library. This library is free // software; you can redistribute it and/or modify it under the // terms of the GNU General Public License as published by the // Free Software Foundation; either version 3, or (at your option) // any later version. // This library is distributed in the hope that it will be useful, // but WITHOUT ANY WARRANTY; without even the implied warranty of // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the // GNU General Public License for more details. // Under Section 7 of GPL version 3, you are granted additional // permissions described in the GCC Runtime Library Exception, version // 3.1, as published by the Free Software Foundation. // You should have received a copy of the GNU General Public License and // a copy of the GCC Runtime Library Exception along with this program; // see the files COPYING3 and COPYING.RUNTIME respectively. If not, see // . /** @file ext/atomicity.h * This file is a GNU extension to the Standard C++ Library. */ #ifndef _GLIBCXX_ATOMICITY_H #define _GLIBCXX_ATOMICITY_H 1 #pragma GCC system_header #include #include #include namespace __gnu_cxx _GLIBCXX_VISIBILITY(default) { _GLIBCXX_BEGIN_NAMESPACE_VERSION // Functions for portable atomic access. // To abstract locking primitives across all thread policies, use: // __exchange_and_add_dispatch // __atomic_add_dispatch #ifdef _GLIBCXX_ATOMIC_BUILTINS static inline _Atomic_word __exchange_and_add(volatile _Atomic_word* __mem, int __val) { return __atomic_fetch_add(__mem, __val, __ATOMIC_ACQ_REL); } static inline void __atomic_add(volatile _Atomic_word* __mem, int __val) { __atomic_fetch_add(__mem, __val, __ATOMIC_ACQ_REL); } #else _Atomic_word __attribute__ ((__unused__)) __exchange_and_add(volatile _Atomic_word*, int) throw (); void __attribute__ ((__unused__)) __atomic_add(volatile _Atomic_word*, int) throw (); #endif static inline _Atomic_word __exchange_and_add_single(_Atomic_word* __mem, int __val) { _Atomic_word __result = *__mem; *__mem += __val; return __result; } static inline void __atomic_add_single(_Atomic_word* __mem, int __val) { *__mem += __val; } static inline _Atomic_word __attribute__ ((__unused__)) __exchange_and_add_dispatch(_Atomic_word* __mem, int __val) { #ifdef __GTHREADS if (__gthread_active_p()) return __exchange_and_add(__mem, __val); else return __exchange_and_add_single(__mem, __val); #else return __exchange_and_add_single(__mem, __val); #endif } static inline void __attribute__ ((__unused__)) __atomic_add_dispatch(_Atomic_word* __mem, int __val) { #ifdef __GTHREADS if (__gthread_active_p()) __atomic_add(__mem, __val); else __atomic_add_single(__mem, __val); #else __atomic_add_single(__mem, __val); #endif } _GLIBCXX_END_NAMESPACE_VERSION } // namespace // Even if the CPU doesn't need a memory barrier, we need to ensure // that the compiler doesn't reorder memory accesses across the // barriers. #ifndef _GLIBCXX_READ_MEM_BARRIER #define _GLIBCXX_READ_MEM_BARRIER __atomic_thread_fence (__ATOMIC_ACQUIRE) #endif #ifndef _GLIBCXX_WRITE_MEM_BARRIER #define _GLIBCXX_WRITE_MEM_BARRIER __atomic_thread_fence (__ATOMIC_RELEASE) #endif #endif PKNd]TT8/ext/debug_allocator.hnu[// Allocators -*- C++ -*- // Copyright (C) 2001-2018 Free Software Foundation, Inc. // // This file is part of the GNU ISO C++ Library. This library is free // software; you can redistribute it and/or modify it under the // terms of the GNU General Public License as published by the // Free Software Foundation; either version 3, or (at your option) // any later version. // This library is distributed in the hope that it will be useful, // but WITHOUT ANY WARRANTY; without even the implied warranty of // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the // GNU General Public License for more details. // Under Section 7 of GPL version 3, you are granted additional // permissions described in the GCC Runtime Library Exception, version // 3.1, as published by the Free Software Foundation. // You should have received a copy of the GNU General Public License and // a copy of the GCC Runtime Library Exception along with this program; // see the files COPYING3 and COPYING.RUNTIME respectively. If not, see // . /* * Copyright (c) 1996-1997 * Silicon Graphics Computer Systems, Inc. * * Permission to use, copy, modify, distribute and sell this software * and its documentation for any purpose is hereby granted without fee, * provided that the above copyright notice appear in all copies and * that both that copyright notice and this permission notice appear * in supporting documentation. Silicon Graphics makes no * representations about the suitability of this software for any * purpose. It is provided "as is" without express or implied warranty. */ /** @file ext/debug_allocator.h * This file is a GNU extension to the Standard C++ Library. */ #ifndef _DEBUG_ALLOCATOR_H #define _DEBUG_ALLOCATOR_H 1 #include #include #include namespace __gnu_cxx _GLIBCXX_VISIBILITY(default) { _GLIBCXX_BEGIN_NAMESPACE_VERSION using std::size_t; /** * @brief A meta-allocator with debugging bits. * @ingroup allocators * * This is precisely the allocator defined in the C++03 Standard. */ template class debug_allocator { template friend class debug_allocator; typedef __alloc_traits<_Alloc> _Traits; public: typedef typename _Traits::size_type size_type; typedef typename _Traits::difference_type difference_type; typedef typename _Traits::pointer pointer; typedef typename _Traits::const_pointer const_pointer; typedef typename _Traits::reference reference; typedef typename _Traits::const_reference const_reference; typedef typename _Traits::value_type value_type; template class rebind { typedef typename _Traits::template rebind<_Up>::other __other; public: typedef debug_allocator<__other> other; }; private: // _M_extra is the number of objects that correspond to the // extra space where debug information is stored. size_type _M_extra; _Alloc _M_allocator; template::other> struct __convertible { }; template struct __convertible<_Alloc2, _Alloc> { typedef void* __type; }; size_type _S_extra() { const size_t __obj_size = sizeof(value_type); return (sizeof(size_type) + __obj_size - 1) / __obj_size; } public: debug_allocator() : _M_extra(_S_extra()) { } template debug_allocator(const debug_allocator<_Alloc2>& __a2, typename __convertible<_Alloc2>::__type = 0) : _M_allocator(__a2._M_allocator), _M_extra(_S_extra()) { } debug_allocator(const _Alloc& __a) : _M_allocator(__a), _M_extra(_S_extra()) { } pointer allocate(size_type __n) { pointer __res = _M_allocator.allocate(__n + _M_extra); size_type* __ps = reinterpret_cast(__res); *__ps = __n; return __res + _M_extra; } pointer allocate(size_type __n, const void* __hint) { pointer __res = _M_allocator.allocate(__n + _M_extra, __hint); size_type* __ps = reinterpret_cast(__res); *__ps = __n; return __res + _M_extra; } void deallocate(pointer __p, size_type __n) { using std::__throw_runtime_error; if (__p) { pointer __real_p = __p - _M_extra; if (*reinterpret_cast(__real_p) != __n) __throw_runtime_error("debug_allocator::deallocate wrong size"); _M_allocator.deallocate(__real_p, __n + _M_extra); } else __throw_runtime_error("debug_allocator::deallocate null pointer"); } void construct(pointer __p, const value_type& __val) { _Traits::construct(_M_allocator, __p, __val); } #if __cplusplus >= 201103L template void construct(_Tp* __p, _Args&&... __args) { _Traits::construct(_M_allocator, __p, std::forward<_Args>(__args)...); } #endif template void destroy(_Tp* __p) { _Traits::destroy(_M_allocator, __p); } size_type max_size() const throw() { return _Traits::max_size(_M_allocator) - _M_extra; } friend bool operator==(const debug_allocator& __lhs, const debug_allocator& __rhs) { return __lhs._M_allocator == __rhs._M_allocator; } }; template inline bool operator!=(const debug_allocator<_Alloc>& __lhs, const debug_allocator<_Alloc>& __rhs) { return !(__lhs == __rhs); } _GLIBCXX_END_NAMESPACE_VERSION } // namespace #endif PKNd]u3iu"u"8/ext/pool_allocator.hnu[// Allocators -*- C++ -*- // Copyright (C) 2001-2018 Free Software Foundation, Inc. // // This file is part of the GNU ISO C++ Library. This library is free // software; you can redistribute it and/or modify it under the // terms of the GNU General Public License as published by the // Free Software Foundation; either version 3, or (at your option) // any later version. // This library is distributed in the hope that it will be useful, // but WITHOUT ANY WARRANTY; without even the implied warranty of // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the // GNU General Public License for more details. // Under Section 7 of GPL version 3, you are granted additional // permissions described in the GCC Runtime Library Exception, version // 3.1, as published by the Free Software Foundation. // You should have received a copy of the GNU General Public License and // a copy of the GCC Runtime Library Exception along with this program; // see the files COPYING3 and COPYING.RUNTIME respectively. If not, see // . /* * Copyright (c) 1996-1997 * Silicon Graphics Computer Systems, Inc. * * Permission to use, copy, modify, distribute and sell this software * and its documentation for any purpose is hereby granted without fee, * provided that the above copyright notice appear in all copies and * that both that copyright notice and this permission notice appear * in supporting documentation. Silicon Graphics makes no * representations about the suitability of this software for any * purpose. It is provided "as is" without express or implied warranty. */ /** @file ext/pool_allocator.h * This file is a GNU extension to the Standard C++ Library. */ #ifndef _POOL_ALLOCATOR_H #define _POOL_ALLOCATOR_H 1 #include #include #include #include #include #include #include #if __cplusplus >= 201103L #include #endif namespace __gnu_cxx _GLIBCXX_VISIBILITY(default) { _GLIBCXX_BEGIN_NAMESPACE_VERSION using std::size_t; using std::ptrdiff_t; /** * @brief Base class for __pool_alloc. * * Uses various allocators to fulfill underlying requests (and makes as * few requests as possible when in default high-speed pool mode). * * Important implementation properties: * 0. If globally mandated, then allocate objects from new * 1. If the clients request an object of size > _S_max_bytes, the resulting * object will be obtained directly from new * 2. In all other cases, we allocate an object of size exactly * _S_round_up(requested_size). Thus the client has enough size * information that we can return the object to the proper free list * without permanently losing part of the object. */ class __pool_alloc_base { protected: enum { _S_align = 8 }; enum { _S_max_bytes = 128 }; enum { _S_free_list_size = (size_t)_S_max_bytes / (size_t)_S_align }; union _Obj { union _Obj* _M_free_list_link; char _M_client_data[1]; // The client sees this. }; static _Obj* volatile _S_free_list[_S_free_list_size]; // Chunk allocation state. static char* _S_start_free; static char* _S_end_free; static size_t _S_heap_size; size_t _M_round_up(size_t __bytes) { return ((__bytes + (size_t)_S_align - 1) & ~((size_t)_S_align - 1)); } _GLIBCXX_CONST _Obj* volatile* _M_get_free_list(size_t __bytes) throw (); __mutex& _M_get_mutex() throw (); // Returns an object of size __n, and optionally adds to size __n // free list. void* _M_refill(size_t __n); // Allocates a chunk for nobjs of size size. nobjs may be reduced // if it is inconvenient to allocate the requested number. char* _M_allocate_chunk(size_t __n, int& __nobjs); }; /** * @brief Allocator using a memory pool with a single lock. * @ingroup allocators */ template class __pool_alloc : private __pool_alloc_base { private: static _Atomic_word _S_force_new; public: typedef size_t size_type; typedef ptrdiff_t difference_type; typedef _Tp* pointer; typedef const _Tp* const_pointer; typedef _Tp& reference; typedef const _Tp& const_reference; typedef _Tp value_type; template struct rebind { typedef __pool_alloc<_Tp1> other; }; #if __cplusplus >= 201103L // _GLIBCXX_RESOLVE_LIB_DEFECTS // 2103. propagate_on_container_move_assignment typedef std::true_type propagate_on_container_move_assignment; #endif __pool_alloc() _GLIBCXX_USE_NOEXCEPT { } __pool_alloc(const __pool_alloc&) _GLIBCXX_USE_NOEXCEPT { } template __pool_alloc(const __pool_alloc<_Tp1>&) _GLIBCXX_USE_NOEXCEPT { } ~__pool_alloc() _GLIBCXX_USE_NOEXCEPT { } pointer address(reference __x) const _GLIBCXX_NOEXCEPT { return std::__addressof(__x); } const_pointer address(const_reference __x) const _GLIBCXX_NOEXCEPT { return std::__addressof(__x); } size_type max_size() const _GLIBCXX_USE_NOEXCEPT { return size_t(-1) / sizeof(_Tp); } #if __cplusplus >= 201103L template void construct(_Up* __p, _Args&&... __args) { ::new((void *)__p) _Up(std::forward<_Args>(__args)...); } template void destroy(_Up* __p) { __p->~_Up(); } #else // _GLIBCXX_RESOLVE_LIB_DEFECTS // 402. wrong new expression in [some_] allocator::construct void construct(pointer __p, const _Tp& __val) { ::new((void *)__p) _Tp(__val); } void destroy(pointer __p) { __p->~_Tp(); } #endif pointer allocate(size_type __n, const void* = 0); void deallocate(pointer __p, size_type __n); }; template inline bool operator==(const __pool_alloc<_Tp>&, const __pool_alloc<_Tp>&) { return true; } template inline bool operator!=(const __pool_alloc<_Tp>&, const __pool_alloc<_Tp>&) { return false; } template _Atomic_word __pool_alloc<_Tp>::_S_force_new; template _Tp* __pool_alloc<_Tp>::allocate(size_type __n, const void*) { pointer __ret = 0; if (__builtin_expect(__n != 0, true)) { if (__n > this->max_size()) std::__throw_bad_alloc(); const size_t __bytes = __n * sizeof(_Tp); #if __cpp_aligned_new if (alignof(_Tp) > __STDCPP_DEFAULT_NEW_ALIGNMENT__) { std::align_val_t __al = std::align_val_t(alignof(_Tp)); return static_cast<_Tp*>(::operator new(__bytes, __al)); } #endif // If there is a race through here, assume answer from getenv // will resolve in same direction. Inspired by techniques // to efficiently support threading found in basic_string.h. if (_S_force_new == 0) { if (std::getenv("GLIBCXX_FORCE_NEW")) __atomic_add_dispatch(&_S_force_new, 1); else __atomic_add_dispatch(&_S_force_new, -1); } if (__bytes > size_t(_S_max_bytes) || _S_force_new > 0) __ret = static_cast<_Tp*>(::operator new(__bytes)); else { _Obj* volatile* __free_list = _M_get_free_list(__bytes); __scoped_lock sentry(_M_get_mutex()); _Obj* __restrict__ __result = *__free_list; if (__builtin_expect(__result == 0, 0)) __ret = static_cast<_Tp*>(_M_refill(_M_round_up(__bytes))); else { *__free_list = __result->_M_free_list_link; __ret = reinterpret_cast<_Tp*>(__result); } if (__ret == 0) std::__throw_bad_alloc(); } } return __ret; } template void __pool_alloc<_Tp>::deallocate(pointer __p, size_type __n) { if (__builtin_expect(__n != 0 && __p != 0, true)) { #if __cpp_aligned_new if (alignof(_Tp) > __STDCPP_DEFAULT_NEW_ALIGNMENT__) { ::operator delete(__p, std::align_val_t(alignof(_Tp))); return; } #endif const size_t __bytes = __n * sizeof(_Tp); if (__bytes > static_cast(_S_max_bytes) || _S_force_new > 0) ::operator delete(__p); else { _Obj* volatile* __free_list = _M_get_free_list(__bytes); _Obj* __q = reinterpret_cast<_Obj*>(__p); __scoped_lock sentry(_M_get_mutex()); __q ->_M_free_list_link = *__free_list; *__free_list = __q; } } } _GLIBCXX_END_NAMESPACE_VERSION } // namespace #endif PKNd].[[8/ext/mt_allocator.hnu[// MT-optimized allocator -*- C++ -*- // Copyright (C) 2003-2018 Free Software Foundation, Inc. // // This file is part of the GNU ISO C++ Library. This library is free // software; you can redistribute it and/or modify it under the // terms of the GNU General Public License as published by the // Free Software Foundation; either version 3, or (at your option) // any later version. // This library is distributed in the hope that it will be useful, // but WITHOUT ANY WARRANTY; without even the implied warranty of // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the // GNU General Public License for more details. // Under Section 7 of GPL version 3, you are granted additional // permissions described in the GCC Runtime Library Exception, version // 3.1, as published by the Free Software Foundation. // You should have received a copy of the GNU General Public License and // a copy of the GCC Runtime Library Exception along with this program; // see the files COPYING3 and COPYING.RUNTIME respectively. If not, see // . /** @file ext/mt_allocator.h * This file is a GNU extension to the Standard C++ Library. */ #ifndef _MT_ALLOCATOR_H #define _MT_ALLOCATOR_H 1 #include #include #include #include #include #if __cplusplus >= 201103L #include #endif namespace __gnu_cxx _GLIBCXX_VISIBILITY(default) { _GLIBCXX_BEGIN_NAMESPACE_VERSION using std::size_t; using std::ptrdiff_t; typedef void (*__destroy_handler)(void*); /// Base class for pool object. struct __pool_base { // Using short int as type for the binmap implies we are never // caching blocks larger than 32768 with this allocator. typedef unsigned short int _Binmap_type; // Variables used to configure the behavior of the allocator, // assigned and explained in detail below. struct _Tune { // Compile time constants for the default _Tune values. enum { _S_align = 8 }; enum { _S_max_bytes = 128 }; enum { _S_min_bin = 8 }; enum { _S_chunk_size = 4096 - 4 * sizeof(void*) }; enum { _S_max_threads = 4096 }; enum { _S_freelist_headroom = 10 }; // Alignment needed. // NB: In any case must be >= sizeof(_Block_record), that // is 4 on 32 bit machines and 8 on 64 bit machines. size_t _M_align; // Allocation requests (after round-up to power of 2) below // this value will be handled by the allocator. A raw new/ // call will be used for requests larger than this value. // NB: Must be much smaller than _M_chunk_size and in any // case <= 32768. size_t _M_max_bytes; // Size in bytes of the smallest bin. // NB: Must be a power of 2 and >= _M_align (and of course // much smaller than _M_max_bytes). size_t _M_min_bin; // In order to avoid fragmenting and minimize the number of // new() calls we always request new memory using this // value. Based on previous discussions on the libstdc++ // mailing list we have chosen the value below. // See http://gcc.gnu.org/ml/libstdc++/2001-07/msg00077.html // NB: At least one order of magnitude > _M_max_bytes. size_t _M_chunk_size; // The maximum number of supported threads. For // single-threaded operation, use one. Maximum values will // vary depending on details of the underlying system. (For // instance, Linux 2.4.18 reports 4070 in // /proc/sys/kernel/threads-max, while Linux 2.6.6 reports // 65534) size_t _M_max_threads; // Each time a deallocation occurs in a threaded application // we make sure that there are no more than // _M_freelist_headroom % of used memory on the freelist. If // the number of additional records is more than // _M_freelist_headroom % of the freelist, we move these // records back to the global pool. size_t _M_freelist_headroom; // Set to true forces all allocations to use new(). bool _M_force_new; explicit _Tune() : _M_align(_S_align), _M_max_bytes(_S_max_bytes), _M_min_bin(_S_min_bin), _M_chunk_size(_S_chunk_size), _M_max_threads(_S_max_threads), _M_freelist_headroom(_S_freelist_headroom), _M_force_new(std::getenv("GLIBCXX_FORCE_NEW") ? true : false) { } explicit _Tune(size_t __align, size_t __maxb, size_t __minbin, size_t __chunk, size_t __maxthreads, size_t __headroom, bool __force) : _M_align(__align), _M_max_bytes(__maxb), _M_min_bin(__minbin), _M_chunk_size(__chunk), _M_max_threads(__maxthreads), _M_freelist_headroom(__headroom), _M_force_new(__force) { } }; struct _Block_address { void* _M_initial; _Block_address* _M_next; }; const _Tune& _M_get_options() const { return _M_options; } void _M_set_options(_Tune __t) { if (!_M_init) _M_options = __t; } bool _M_check_threshold(size_t __bytes) { return __bytes > _M_options._M_max_bytes || _M_options._M_force_new; } size_t _M_get_binmap(size_t __bytes) { return _M_binmap[__bytes]; } size_t _M_get_align() { return _M_options._M_align; } explicit __pool_base() : _M_options(_Tune()), _M_binmap(0), _M_init(false) { } explicit __pool_base(const _Tune& __options) : _M_options(__options), _M_binmap(0), _M_init(false) { } private: explicit __pool_base(const __pool_base&); __pool_base& operator=(const __pool_base&); protected: // Configuration options. _Tune _M_options; _Binmap_type* _M_binmap; // Configuration of the pool object via _M_options can happen // after construction but before initialization. After // initialization is complete, this variable is set to true. bool _M_init; }; /** * @brief Data describing the underlying memory pool, parameterized on * threading support. */ template class __pool; /// Specialization for single thread. template<> class __pool : public __pool_base { public: union _Block_record { // Points to the block_record of the next free block. _Block_record* _M_next; }; struct _Bin_record { // An "array" of pointers to the first free block. _Block_record** _M_first; // A list of the initial addresses of all allocated blocks. _Block_address* _M_address; }; void _M_initialize_once() { if (__builtin_expect(_M_init == false, false)) _M_initialize(); } void _M_destroy() throw(); char* _M_reserve_block(size_t __bytes, const size_t __thread_id); void _M_reclaim_block(char* __p, size_t __bytes) throw (); size_t _M_get_thread_id() { return 0; } const _Bin_record& _M_get_bin(size_t __which) { return _M_bin[__which]; } void _M_adjust_freelist(const _Bin_record&, _Block_record*, size_t) { } explicit __pool() : _M_bin(0), _M_bin_size(1) { } explicit __pool(const __pool_base::_Tune& __tune) : __pool_base(__tune), _M_bin(0), _M_bin_size(1) { } private: // An "array" of bin_records each of which represents a specific // power of 2 size. Memory to this "array" is allocated in // _M_initialize(). _Bin_record* _M_bin; // Actual value calculated in _M_initialize(). size_t _M_bin_size; void _M_initialize(); }; #ifdef __GTHREADS /// Specialization for thread enabled, via gthreads.h. template<> class __pool : public __pool_base { public: // Each requesting thread is assigned an id ranging from 1 to // _S_max_threads. Thread id 0 is used as a global memory pool. // In order to get constant performance on the thread assignment // routine, we keep a list of free ids. When a thread first // requests memory we remove the first record in this list and // stores the address in a __gthread_key. When initializing the // __gthread_key we specify a destructor. When this destructor // (i.e. the thread dies) is called, we return the thread id to // the front of this list. struct _Thread_record { // Points to next free thread id record. NULL if last record in list. _Thread_record* _M_next; // Thread id ranging from 1 to _S_max_threads. size_t _M_id; }; union _Block_record { // Points to the block_record of the next free block. _Block_record* _M_next; // The thread id of the thread which has requested this block. size_t _M_thread_id; }; struct _Bin_record { // An "array" of pointers to the first free block for each // thread id. Memory to this "array" is allocated in // _S_initialize() for _S_max_threads + global pool 0. _Block_record** _M_first; // A list of the initial addresses of all allocated blocks. _Block_address* _M_address; // An "array" of counters used to keep track of the amount of // blocks that are on the freelist/used for each thread id. // - Note that the second part of the allocated _M_used "array" // actually hosts (atomic) counters of reclaimed blocks: in // _M_reserve_block and in _M_reclaim_block those numbers are // subtracted from the first ones to obtain the actual size // of the "working set" of the given thread. // - Memory to these "arrays" is allocated in _S_initialize() // for _S_max_threads + global pool 0. size_t* _M_free; size_t* _M_used; // Each bin has its own mutex which is used to ensure data // integrity while changing "ownership" on a block. The mutex // is initialized in _S_initialize(). __gthread_mutex_t* _M_mutex; }; // XXX GLIBCXX_ABI Deprecated void _M_initialize(__destroy_handler); void _M_initialize_once() { if (__builtin_expect(_M_init == false, false)) _M_initialize(); } void _M_destroy() throw(); char* _M_reserve_block(size_t __bytes, const size_t __thread_id); void _M_reclaim_block(char* __p, size_t __bytes) throw (); const _Bin_record& _M_get_bin(size_t __which) { return _M_bin[__which]; } void _M_adjust_freelist(const _Bin_record& __bin, _Block_record* __block, size_t __thread_id) { if (__gthread_active_p()) { __block->_M_thread_id = __thread_id; --__bin._M_free[__thread_id]; ++__bin._M_used[__thread_id]; } } // XXX GLIBCXX_ABI Deprecated void _M_destroy_thread_key(void*) throw (); size_t _M_get_thread_id(); explicit __pool() : _M_bin(0), _M_bin_size(1), _M_thread_freelist(0) { } explicit __pool(const __pool_base::_Tune& __tune) : __pool_base(__tune), _M_bin(0), _M_bin_size(1), _M_thread_freelist(0) { } private: // An "array" of bin_records each of which represents a specific // power of 2 size. Memory to this "array" is allocated in // _M_initialize(). _Bin_record* _M_bin; // Actual value calculated in _M_initialize(). size_t _M_bin_size; _Thread_record* _M_thread_freelist; void* _M_thread_freelist_initial; void _M_initialize(); }; #endif template