diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt index a58d6d205..24c282d0f 100644 --- a/src/CMakeLists.txt +++ b/src/CMakeLists.txt @@ -56,6 +56,7 @@ Set(SOURCEPYTHON_UTILITIES_HEADERS core/utilities/wrap_macros.h core/utilities/conversions.h core/utilities/ipythongenerator.h + core/utilities/array.h ) Set(SOURCEPYTHON_UTILITIES_SOURCES diff --git a/src/core/modules/core/core_wrap.cpp b/src/core/modules/core/core_wrap.cpp index a0abf7199..1379b0e0b 100644 --- a/src/core/modules/core/core_wrap.cpp +++ b/src/core/modules/core/core_wrap.cpp @@ -30,6 +30,7 @@ #include "export_main.h" #include "sp_main.h" #include "core.h" +#include "utilities/array.h" //----------------------------------------------------------------------------- @@ -46,6 +47,7 @@ static void export_message_severity(scope); static void export_output_return(scope); static void export_constants(scope); static void export_functions(scope); +static void export_arrays(scope); //----------------------------------------------------------------------------- @@ -58,6 +60,7 @@ DECLARE_SP_MODULE(_core) export_output_return(_core); export_constants(_core); export_functions(_core); + export_arrays(_core); scope().attr("BoostPythonClass") = objects::class_metatype(); } @@ -135,3 +138,65 @@ void export_functions(scope _core) "Return a list of all modules exposed by Source.Python's core.\n\n" ":rtype: list"); } + +//----------------------------------------------------------------------------- +// Expose functions. +//----------------------------------------------------------------------------- +void export_arrays(scope _core) +{ + class_< Array >( "BoolArray" ) + .def(array_indexing_suite< Array >()) + ; + + class_< Array >( "CharArray" ) + .def(array_indexing_suite< Array >()) + ; + + class_< Array >( "UCharArray" ) + .def(array_indexing_suite< Array >()) + ; + + class_< Array >( "UShortArray" ) + .def(array_indexing_suite< Array >()) + ; + + class_< Array >( "ShortArray" ) + .def(array_indexing_suite< Array >()) + ; + + class_< Array >( "IntArray" ) + .def(array_indexing_suite< Array >()) + ; + + class_< Array >( "UIntArray" ) + .def(array_indexing_suite< Array >()) + ; + + class_< Array >( "LongArray" ) + .def(array_indexing_suite< Array >()) + ; + + class_< Array >( "ULongArray" ) + .def(array_indexing_suite< Array >()) + ; + + class_< Array >( "LongLongArray" ) + .def(array_indexing_suite< Array >()) + ; + + class_< Array >( "ULongLongArray" ) + .def(array_indexing_suite< Array >()) + ; + + class_< Array >( "FloatArray" ) + .def(array_indexing_suite< Array >()) + ; + + class_< Array >( "DoubleArray" ) + .def(array_indexing_suite< Array >()) + ; + + //class_< Array >( "StringArray" ) + // .def(array_indexing_suite< Array >()) + //; +} \ No newline at end of file diff --git a/src/core/utilities/array.h b/src/core/utilities/array.h new file mode 100644 index 000000000..8af4ed5e0 --- /dev/null +++ b/src/core/utilities/array.h @@ -0,0 +1,349 @@ +/** +* ============================================================================= +* Source Python +* Copyright (C) 2012-2020 Source Python Development Team. All rights reserved. +* ============================================================================= +* +* This program is free software; you can redistribute it and/or modify it under +* the terms of the GNU General Public License, version 3.0, as published by the +* Free Software Foundation. +* +* This program 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. +* +* You should have received a copy of the GNU General Public License along with +* this program. If not, see . +* +* As a special exception, the Source Python Team gives you permission +* to link the code of this program (as well as its derivative works) to +* "Half-Life 2," the "Source Engine," and any Game MODs that run on software +* by the Valve Corporation. You must obey the GNU General Public License in +* all respects for all other code used. Additionally, the Source.Python +* Development Team grants this exception to all derivative works. +*/ + +#ifndef _ARRAY_H +#define _ARRAY_H + +// ============================================================================ +// >> INCLUDES +// ============================================================================ +#include "utilities/wrap_macros.h" +#include "modules/memory/memory_utilities.h" + +#include +#include + +#include +#include +#include +#include + + +// ============================================================================ +// >> Array +// ============================================================================ +// Implementation is based on this: +// https://stackoverflow.com/a/27560620 +template +class Array +{ +public: + typedef T* pointer; + typedef T value_type; + typedef std::size_t size_type; + typedef T* iterator; + typedef T const* const_iterator; + typedef std::reverse_iterator reverse_iterator; + typedef std::reverse_iterator const_reverse_iterator; + + Array() + : arr_(NULL), + length_(-1) + {} + + Array(pointer arr) + : arr_(arr), + length_(-1) + {} + + Array(void* arr) + : arr_(reinterpret_cast(arr)), + length_(-1) + {} + + Array(void* arr, size_type length) + : arr_(reinterpret_cast(arr)), + length_(length) + {} + + Array(pointer arr, size_type length) + : arr_(arr), + length_(length) + {} + + Array( pointer first, pointer last ) + : arr_(first), + length_(static_cast(std::distance(first, last))) + {} + + T& operator[](size_type index) + { + return arr_[index]; + } + + iterator begin() + { + return arr_; + } + + const_iterator cbegin() const + { + return arr_; + } + + iterator end() + { + return begin() + size(); + } + + const_iterator cend() const + { + return cbegin() + size(); + } + + reverse_iterator rbegin() + { + return reverse_iterator( end() ); + } + + const_reverse_iterator rbegin() const + { + return const_reverse_iterator( cend() ); + } + + const_reverse_iterator crbegin() const + { + return const_reverse_iterator( cend() ); + } + + reverse_iterator rend() + { + return reverse_iterator( begin() ); + } + + const_reverse_iterator rend() const + { + return const_reverse_iterator( cbegin() ); + } + + const_reverse_iterator crend() const + { + return const_reverse_iterator( cbegin() ); + } + + size_type size() const + { + validate_length(); + return length_; + } + + void check_index(size_type index) const + { + size_type length = size(); + if (!(0 <= index < length)) + BOOST_RAISE_EXCEPTION(PyExc_IndexError, "Index (%d) out of range (%d)", index, length) + } + + void validate_length() const + { + if (!has_length()) + BOOST_RAISE_EXCEPTION(PyExc_TypeError, "Operation requires length of the array.") + } + + bool has_length() const + { + return length_ != -1; + } + + static void set_length(Array& arr, size_type size) + { + arr.length_ = size; + } + +protected: + iterator arr_; + size_type length_; +}; + + +// ============================================================================ +// >> array_indexing_suite +// ============================================================================ +// Forward declaration +template< + typename Array, + bool NoProxy, + typename DerivedPolicies> +class array_indexing_suite; + + +namespace detail { + +template +struct final_array_derived_policies +: array_indexing_suite> +{}; + +} /* namespace detail */ + + +template< + typename Array, + bool NoProxy = std::is_arithmetic::value, + typename DerivedPolicies = ::detail::final_array_derived_policies +> +class array_indexing_suite + : public boost::python::indexing_suite +{ +public: + typedef typename Array::value_type data_type; + typedef typename Array::value_type key_type; + typedef typename Array::size_type index_type; + typedef typename Array::size_type size_type; + + template + static void extension_def(Class& cl) + { + cl + .def(init()) + .def(init()) + .def("set_length", Array::set_length) + + .def(GET_PTR_NAME, &get_ptr, manage_new_object_policy()) + .def(GET_OBJ_NAME, &make_obj, manage_new_object_policy()).staticmethod(GET_OBJ_NAME) + .add_property(GET_SIZE_NAME, &get_size) + ; + + extern dict g_oExposedClasses; + g_oExposedClasses[cl.attr("__name__")] = cl; + } + + static CPointer* get_ptr(Array& arr) + { + return new CPointer((unsigned long) arr.begin()); + } + + static Array* make_obj(CPointer* pPtr) + { + return new Array((void *) pPtr->m_ulAddr); + } + + static size_type get_size(Array& arr) + { + return arr.size() * sizeof(data_type); + } + + static data_type & get_item(Array & arr, index_type i) { + return arr[i]; + } + + static void set_item(Array & arr, index_type i, data_type const & v) { + arr[i] = v; + } + + static void delete_item(Array & arr, index_type i) { + BOOST_RAISE_EXCEPTION(PyExc_NotImplementedError, "delete_item") + } + + static size_type size(Array & arr) { + return arr.size(); + } + + static bool contains(Array & arr, key_type const & key) { + return std::find(arr.cbegin(), arr.cend(), key) != arr.cend(); + } + + static index_type get_min_index(Array & arr) { + return 0; + } + + static index_type get_max_index(Array & arr) { + return arr.size(); + } + + static bool compare_index(Array & , index_type a, index_type b) { + return a < b; + } + + static index_type convert_index(Array & arr, PyObject * i_) { + boost::python::extract < long > i(i_); + if (i.check()) { + long index = i(); + + if (index < 0) { + index += static_cast < decltype(index) > (DerivedPolicies::size(arr)); + } + + // This allows wrapping raw pointers and treat them like an array. + // The programmer has to take care of not exceeding the array size. + if (arr.has_length()) + arr.validate_length(); + + return index; + } + + BOOST_RAISE_EXCEPTION(PyExc_TypeError, "Invalid index type"); + + return index_type(); + } + + static boost::python::object get_slice(Array & arr, index_type from, index_type to) { + if (from > to) { + return boost::python::object(Array()); + } + return boost::python::object(Array(arr.begin() + from, arr.begin() + to)); + } + + static void set_slice(Array & arr, index_type from, index_type to, data_type + const & v) { + if (from > to) { + return; + + } else if (to > arr.size()) { + BOOST_RAISE_EXCEPTION(PyExc_IndexError, "Index out of range"); + + } else { + std::fill(arr.begin() + from, arr.begin() + to, v); + + } + } + + template < typename Iter > + static void set_slice(Array & arr, index_type from, index_type to, Iter first, Iter last) { + auto num_items = std::distance(first, last); + + if ((from + num_items) > arr.size()) { + BOOST_RAISE_EXCEPTION(PyExc_IndexError, "Index out of range"); + } + + if (from > to) { + std::copy(first, last, arr.begin() + from); + + } else { + if (static_cast < decltype(num_items) > (to - from) != num_items) { + BOOST_RAISE_EXCEPTION(PyExc_TypeError, "Array length is immutable"); + } + + std::copy(first, last, arr.begin() + from); + } + } + + static void delete_slice(Array & arr, index_type from , index_type to) { + BOOST_RAISE_EXCEPTION(PyExc_NotImplementedError, "delete_slice") + } +}; + +#endif // _ARRAY_H \ No newline at end of file pFad - Phonifier reborn

Pfad - The Proxy pFad of © 2024 Garber Painting. All rights reserved.

Note: This service is not intended for secure transactions such as banking, social media, email, or purchasing. Use at your own risk. We assume no liability whatsoever for broken pages.


Alternative Proxies:

Alternative Proxy

pFad Proxy

pFad v3 Proxy

pFad v4 Proxy