diff options
author | Devtools Arcadia <arcadia-devtools@yandex-team.ru> | 2022-02-07 18:08:42 +0300 |
---|---|---|
committer | Devtools Arcadia <arcadia-devtools@mous.vla.yp-c.yandex.net> | 2022-02-07 18:08:42 +0300 |
commit | 1110808a9d39d4b808aef724c861a2e1a38d2a69 (patch) | |
tree | e26c9fed0de5d9873cce7e00bc214573dc2195b7 /contrib/restricted/boost/libs/python/src/converter/registry.cpp | |
download | ydb-1110808a9d39d4b808aef724c861a2e1a38d2a69.tar.gz |
intermediate changes
ref:cde9a383711a11544ce7e107a78147fb96cc4029
Diffstat (limited to 'contrib/restricted/boost/libs/python/src/converter/registry.cpp')
-rw-r--r-- | contrib/restricted/boost/libs/python/src/converter/registry.cpp | 306 |
1 files changed, 306 insertions, 0 deletions
diff --git a/contrib/restricted/boost/libs/python/src/converter/registry.cpp b/contrib/restricted/boost/libs/python/src/converter/registry.cpp new file mode 100644 index 0000000000..aa20c3f685 --- /dev/null +++ b/contrib/restricted/boost/libs/python/src/converter/registry.cpp @@ -0,0 +1,306 @@ +// Copyright David Abrahams 2001. +// Distributed under the Boost Software License, Version 1.0. (See +// accompanying file LICENSE_1_0.txt or copy at +// http://www.boost.org/LICENSE_1_0.txt) +#include <boost/python/converter/registry.hpp> +#include <boost/python/converter/registrations.hpp> +#include <boost/python/converter/builtin_converters.hpp> + +#include <set> +#include <stdexcept> + +#if defined(__APPLE__) && defined(__MACH__) && defined(__GNUC__) \ + && __GNUC__ == 3 && __GNUC_MINOR__ <= 4 && !defined(__APPLE_CC__) +# define BOOST_PYTHON_CONVERTER_REGISTRY_APPLE_MACH_WORKAROUND +#endif + +#if defined(BOOST_PYTHON_TRACE_REGISTRY) \ + || defined(BOOST_PYTHON_CONVERTER_REGISTRY_APPLE_MACH_WORKAROUND) +# include <iostream> +#endif + +namespace boost { namespace python { namespace converter { +BOOST_PYTHON_DECL PyTypeObject const* registration::expected_from_python_type() const +{ + if (this->m_class_object != 0) + return this->m_class_object; + + std::set<PyTypeObject const*> pool; + + for(rvalue_from_python_chain* r = rvalue_chain; r ; r=r->next) + if(r->expected_pytype) + pool.insert(r->expected_pytype()); + + //for now I skip the search for common base + if (pool.size()==1) + return *pool.begin(); + + return 0; + +} + +BOOST_PYTHON_DECL PyTypeObject const* registration::to_python_target_type() const +{ + if (this->m_class_object != 0) + return this->m_class_object; + + if (this->m_to_python_target_type != 0) + return this->m_to_python_target_type(); + + return 0; +} + +BOOST_PYTHON_DECL PyTypeObject* registration::get_class_object() const +{ + if (this->m_class_object == 0) + { + ::PyErr_Format( + PyExc_TypeError + , const_cast<char*>("No Python class registered for C++ class %s") + , this->target_type.name()); + + throw_error_already_set(); + } + + return this->m_class_object; +} + +BOOST_PYTHON_DECL PyObject* registration::to_python(void const volatile* source) const +{ + if (this->m_to_python == 0) + { + handle<> msg( +#if PY_VERSION_HEX >= 0x3000000 + ::PyUnicode_FromFormat +#else + ::PyString_FromFormat +#endif + ( + "No to_python (by-value) converter found for C++ type: %s" + , this->target_type.name() + ) + ); + + PyErr_SetObject(PyExc_TypeError, msg.get()); + + throw_error_already_set(); + } + + return source == 0 + ? incref(Py_None) + : this->m_to_python(const_cast<void*>(source)); +} + +namespace +{ + template< typename T > + void delete_node( T* node ) + { + if( !!node && !!node->next ) + delete_node( node->next ); + delete node; + } +} + +registration::~registration() +{ + delete_node(lvalue_chain); + delete_node(rvalue_chain); +} + + +namespace // <unnamed> +{ + typedef registration entry; + + typedef std::set<entry> registry_t; + +#ifndef BOOST_PYTHON_CONVERTER_REGISTRY_APPLE_MACH_WORKAROUND + registry_t& entries() + { + static registry_t registry; + +# ifndef BOOST_PYTHON_SUPPRESS_REGISTRY_INITIALIZATION + static bool builtin_converters_initialized = false; + if (!builtin_converters_initialized) + { + // Make this true early because registering the builtin + // converters will cause recursion. + builtin_converters_initialized = true; + + initialize_builtin_converters(); + } +# ifdef BOOST_PYTHON_TRACE_REGISTRY + std::cout << "registry: "; + for (registry_t::iterator p = registry.begin(); p != registry.end(); ++p) + { + std::cout << p->target_type << "; "; + } + std::cout << '\n'; +# endif +# endif + return registry; + } +#else + registry_t& static_registry() + { + static registry_t result; + return result; + } + + bool static_builtin_converters_initialized() + { + static bool result = false; + if (result == false) { + result = true; + std::cout << std::flush; + return false; + } + return true; + } + + registry_t& entries() + { +# ifndef BOOST_PYTHON_SUPPRESS_REGISTRY_INITIALIZATION + if (!static_builtin_converters_initialized()) + { + initialize_builtin_converters(); + } +# ifdef BOOST_PYTHON_TRACE_REGISTRY + std::cout << "registry: "; + for (registry_t::iterator p = static_registry().begin(); p != static_registry().end(); ++p) + { + std::cout << p->target_type << "; "; + } + std::cout << '\n'; +# endif +# endif + return static_registry(); + } +#endif // BOOST_PYTHON_CONVERTER_REGISTRY_APPLE_MACH_WORKAROUND + + entry* get(type_info type, bool is_shared_ptr = false) + { +# ifdef BOOST_PYTHON_TRACE_REGISTRY + registry_t::iterator p = entries().find(entry(type)); + + std::cout << "looking up " << type << ": " + << (p == entries().end() || p->target_type != type + ? "...NOT found\n" : "...found\n"); +# endif + std::pair<registry_t::const_iterator,bool> pos_ins + = entries().insert(entry(type,is_shared_ptr)); + +# if __MWERKS__ >= 0x3000 + // do a little invariant checking if a change was made + if ( pos_ins.second ) + assert(entries().invariants()); +# endif + return const_cast<entry*>(&*pos_ins.first); + } +} // namespace <unnamed> + +namespace registry +{ + void insert(to_python_function_t f, type_info source_t, PyTypeObject const* (*to_python_target_type)()) + { +# ifdef BOOST_PYTHON_TRACE_REGISTRY + std::cout << "inserting to_python " << source_t << "\n"; +# endif + entry* slot = get(source_t); + + assert(slot->m_to_python == 0); // we have a problem otherwise + if (slot->m_to_python != 0) + { + std::string msg = ( + std::string("to-Python converter for ") + + source_t.name() + + " already registered; second conversion method ignored." + ); + + if ( ::PyErr_Warn( NULL, const_cast<char*>(msg.c_str()) ) ) + { + throw_error_already_set(); + } + } + slot->m_to_python = f; + slot->m_to_python_target_type = to_python_target_type; + } + + // Insert an lvalue from_python converter + void insert(convertible_function convert, type_info key, PyTypeObject const* (*exp_pytype)()) + { +# ifdef BOOST_PYTHON_TRACE_REGISTRY + std::cout << "inserting lvalue from_python " << key << "\n"; +# endif + entry* found = get(key); + lvalue_from_python_chain *registration = new lvalue_from_python_chain; + registration->convert = convert; + registration->next = found->lvalue_chain; + found->lvalue_chain = registration; + + insert(convert, 0, key,exp_pytype); + } + + // Insert an rvalue from_python converter + void insert(convertible_function convertible + , constructor_function construct + , type_info key + , PyTypeObject const* (*exp_pytype)()) + { +# ifdef BOOST_PYTHON_TRACE_REGISTRY + std::cout << "inserting rvalue from_python " << key << "\n"; +# endif + entry* found = get(key); + rvalue_from_python_chain *registration = new rvalue_from_python_chain; + registration->convertible = convertible; + registration->construct = construct; + registration->expected_pytype = exp_pytype; + registration->next = found->rvalue_chain; + found->rvalue_chain = registration; + } + + // Insert an rvalue from_python converter + void push_back(convertible_function convertible + , constructor_function construct + , type_info key + , PyTypeObject const* (*exp_pytype)()) + { +# ifdef BOOST_PYTHON_TRACE_REGISTRY + std::cout << "push_back rvalue from_python " << key << "\n"; +# endif + rvalue_from_python_chain** found = &get(key)->rvalue_chain; + while (*found != 0) + found = &(*found)->next; + + rvalue_from_python_chain *registration = new rvalue_from_python_chain; + registration->convertible = convertible; + registration->construct = construct; + registration->expected_pytype = exp_pytype; + registration->next = 0; + *found = registration; + } + + registration const& lookup(type_info key) + { + return *get(key); + } + + registration const& lookup_shared_ptr(type_info key) + { + return *get(key, true); + } + + registration const* query(type_info type) + { + registry_t::iterator p = entries().find(entry(type)); +# ifdef BOOST_PYTHON_TRACE_REGISTRY + std::cout << "querying " << type + << (p == entries().end() || p->target_type != type + ? "...NOT found\n" : "...found\n"); +# endif + return (p == entries().end() || p->target_type != type) ? 0 : &*p; + } +} // namespace registry + +}}} // namespace boost::python::converter |