diff --git a/alib2std/src/alib/ptr_array b/alib2std/src/alib/ptr_array new file mode 100644 index 0000000000000000000000000000000000000000..810145250e2df9f441dbd8f384cf62408acbe897 --- /dev/null +++ b/alib2std/src/alib/ptr_array @@ -0,0 +1 @@ +#include <extensions/ptr_array.hpp> diff --git a/alib2std/src/extensions/ptr_array.hpp b/alib2std/src/extensions/ptr_array.hpp new file mode 100644 index 0000000000000000000000000000000000000000..0f9b348fd9dc9a8beb231432a0bd0e72e11d1cbf --- /dev/null +++ b/alib2std/src/extensions/ptr_array.hpp @@ -0,0 +1,352 @@ +/* + * ptr_array.hpp + * + * Created on: Feb 28, 2014 + * Author: Jan Travnicek + */ + +#ifndef __PTR_ARRAY_HPP_ +#define __PTR_ARRAY_HPP_ + +#include <ostream> +#include <sstream> +#include <string> + +#include "array.hpp" +#include "compare.hpp" +#include "iterator.hpp" +#include "clone.hpp" + +namespace ext { + +template < class T, std::size_t N > +class ptr_array { + std::array < T *, N > m_data; + +public: + + using value_type = T; + + using size_type = std::size_t; + using diference_type = std::ptrdiff_t; + + using reference = value_type &; + using const_reference = const value_type &; + using pointer = T *; + using const_pointer = T * const; + + using iterator = dereferencing_iterator < typename std::array < T *, N >::iterator >; + using const_iterator = dereferencing_iterator < typename std::array < T *, N >::const_iterator >; + + using reverse_iterator = dereferencing_iterator < typename std::array < T *, N >::reverse_iterator >; + using const_reverse_iterator = dereferencing_iterator < typename std::array < T *, N >::const_reverse_iterator >; + + template < class ... Types > + ptr_array ( Types && ... args ) : m_data ( make_array ( ext::clone ( std::forward < Types > ( args ) ) ... ) ) { + } + + ptr_array ( ) { + for ( size_type i = 0; i < N; ++ i ) + m_data.at ( i ) = nullptr; + } + + ptr_array ( const ptr_array& other ) { + for ( size_type i = 0; i < N; ++ i ) + m_data.at ( i ) = ext::clone ( other.at ( i ) ); + } + + ptr_array ( ptr_array && other ) noexcept { + for ( size_type i = 0; i < N; ++ i ) + m_data.at ( i ) = ext::clone ( std::move ( other.at ( i ) ) ); + } + + ~ptr_array ( ) { + for ( size_type i = 0; i < N; ++ i ) + delete m_data.at ( i ); + } + + ptr_array < T, N > & operator = ( const ptr_array < T, N > & other ) { + if ( this == & other ) + return * this; + + for ( size_type i = 0; i < N; ++ i ) { + delete m_data.at ( i ); + m_data.at ( i ) = ext::clone ( other.at ( i ) ); + } + + return *this; + } + + ptr_array < T, N > & operator = ( ptr_array < T, N > && other ) { + std::swap ( m_data, other.m_data ); + + return *this; + } + + template < class R > + void fill ( const R & value ) { + for ( size_type i = 0; i < N; ++ i ) + m_data.at ( i ) = ext::clone ( value ); + } + + reference at ( size_type index ) { + return * m_data.at ( index ); + } + + const_reference at ( size_type index ) const { + return * m_data.at ( index ); + } + + reference operator [ ] ( size_type index ) { + return * m_data [ index ]; + } + + const_reference operator [ ] ( size_type index ) const { + return * m_data [ index ]; + } + + reference front ( ) { + return * m_data.front ( ); + } + + const_reference front ( ) const { + return * m_data.front ( ); + } + + reference back ( ) { + return * m_data.back ( ); + } + + const_reference back ( ) const { + return * m_data.back ( ); + } + + bool null ( size_type index ) const { + return m_data.at ( index ) == NULL; + } + + /* T * const * data ( ) noexcept { + return m_data.data ( ); + } + + T const * const * data ( ) const noexcept { + return m_data.data ( ); + } */ + + iterator begin ( ) noexcept { + return dereferencer ( m_data.begin ( ) ); + } + + const_iterator begin ( ) const noexcept { + return dereferencer ( m_data.begin ( ) ); + } + + const_iterator cbegin ( ) const noexcept { + return dereferencer ( m_data.cbegin ( ) ); + } + + iterator end ( ) noexcept { + return dereferencer ( m_data.end ( ) ); + } + + const_iterator end ( ) const noexcept { + return dereferencer ( m_data.end ( ) ); + } + + const_iterator cend ( ) const noexcept { + return dereferencer ( m_data.cend ( ) ); + } + + reverse_iterator rbegin ( ) noexcept { + return dereferencer ( m_data.rbegin ( ) ); + } + + const_reverse_iterator rbegin ( ) const noexcept { + return dereferencer ( m_data.rbegin ( ) ); + } + + const_reverse_iterator crbegin ( ) const noexcept { + return dereferencer ( m_data.crbegin ( ) ); + } + + reverse_iterator rend ( ) noexcept { + return dereferencer ( m_data.rend ( ) ); + } + + const_reverse_iterator rend ( ) const noexcept { + return dereferencer ( m_data.rend ( ) ); + } + + const_reverse_iterator crend ( ) const noexcept { + return dereferencer ( m_data.crend ( ) ); + } + + bool empty ( ) const noexcept { + return m_data.empty ( ); + } + + size_type size ( ) const noexcept { + return m_data.size ( ); + } + + size_type max_size ( ) const noexcept { + return m_data.max_size ( ); + } + + void reserve ( size_type new_cap ) { + m_data.reserve ( new_cap ); + } + + size_type capacity ( ) const noexcept { + return m_data.capacity ( ); + } + + void shrink_to_fit ( ) { + m_data.shrink_to_fit ( ); + } + + template < class R > + iterator set ( const_iterator pos, R && value ) { + m_data.at ( std::distance ( cbegin ( ), pos ) ) = ext::clone ( std::forward < R > ( value ) ); + return dereferencer ( m_data.begin ( ) + std::distance ( cbegin ( ), pos ) ); + } + + template < class R > + iterator set ( const_iterator pos, T * value ) { + m_data.at ( std::distance ( cbegin ( ), pos ) ) = value ; + return dereferencer ( m_data.begin ( ) + std::distance ( cbegin ( ), pos ) ); + } + + template < class R, class ... Args > + iterator emplace_set ( const_iterator pos, Args && ... args ) { + m_data.at ( std::distance ( cbegin ( ), pos ) ) = new R ( std::forward < Args > ( args ) ... ) ; + return dereferencer ( m_data.begin ( ) + std::distance ( cbegin ( ), pos ) ); + } + + void swap ( ptr_array & other ) { + swap ( this->m_data, other.m_data ); + } + + template < std::size_t I > + auto & get ( ) & { + return * std::get < I > ( m_data ); + } + + template < std::size_t I > + const auto & get ( ) const & { + return * std::get < I > ( m_data ); + } + + template < std::size_t I > + auto && get ( ) && { + return std::move ( * std::get < I > ( m_data ) ); + } +}; + +} /* namespace ext */ + +namespace std { + +template < class ... Ts > +void swap ( ext::ptr_array < Ts ... > & first, ext::ptr_array < Ts ... > & second ) { + first.swap ( second ); +} + +template < std::size_t I, class Type, std::size_t N > +auto & get ( ext::ptr_array < Type, N > & tpl ) { + return tpl.template get < I > ( ); +} + +template < std::size_t I, class Type, std::size_t N > +const auto & get ( const ext::ptr_array < Type, N > & tpl ) { + return tpl.template get < I > ( ); +} + +template < std::size_t I, class Type, std::size_t N > +auto && get ( ext::ptr_array < Type, N> && tpl ) { + return tpl.template get < I > ( ); +} + +} /* namespace std */ + +namespace ext { + +template < class T, std::size_t N > +std::ostream& operator<<(std::ostream& out, const ext::ptr_array < T, N > & ptr_array) { + out << "["; + + bool first = true; + for(const T& item : ptr_array) { + if(!first) out << ", "; + first = false; + out << item; + } + + out << "]"; + return out; +} + +template < class T, std::size_t N > +struct compare < ext::ptr_array < T, N > > { + int operator()(const ext::ptr_array < T, N > & first, const ext::ptr_array < T, N > & second) const { + static compare<typename std::decay < T >::type > comp; + for(auto iterF = first.begin(), iterS = second.begin(); iterF != first.end(); ++iterF, ++iterS) { + int res = comp(*iterF, *iterS); + if(res != 0) return res; + } + return 0; + } +}; + +template < class T, std::size_t N > +std::string to_string ( const ext::ptr_array < T, N > & value ) { + std::stringstream ss; + ss << value; + return ss.str(); +} + +template < class T, std::size_t N > +bool operator == ( const ptr_array < T, N > & first, const ptr_array < T, N > & second ) { + static compare < ptr_array < T, N > > comp; + return comp ( first, second ) == 0; +} + +template < class T, std::size_t N > +bool operator != ( const ptr_array < T, N > & first, const ptr_array < T, N > & second ) { + return ! ( first == second ); +} + +template < class T, std::size_t N > +bool operator < ( const ptr_array < T, N > & first, const ptr_array < T, N > & second ) { + static compare < ptr_array < T, N > > comp; + return comp ( first, second ) < 0; +} + +template < class T, std::size_t N > +bool operator > ( const ptr_array < T, N > & first, const ptr_array < T, N > & second ) { + return second < first; +} + +template < class T, std::size_t N > +bool operator <= ( const ptr_array < T, N > & first, const ptr_array < T, N > & second ) { + return ! ( first > second ); +} + +template < class T, std::size_t N > +bool operator >= ( const ptr_array < T, N > & first, const ptr_array < T, N > & second ) { + return ! ( first < second ); +} + +template < typename Base, typename ... Types > +constexpr ptr_array < typename std::remove_reference < Base >::type , sizeof ... ( Types ) + 1 > make_ptr_array ( Base && first, Types && ... other ) { + return ptr_array < typename std::remove_reference < Base >::type, sizeof ... ( Types ) + 1 > ( std::forward < Base > ( first ), std::forward < Types > ( other ) ... ); +} + +template < typename Base > +constexpr ptr_array < typename std::remove_reference < Base >::type, 0 > make_ptr_array ( ) { + return ptr_array < typename std::remove_reference < Base >::type, 0 > ( ); +} + +} /* namespace ext */ + +#endif /* __PTR_ARRAY_HPP_ */ diff --git a/alib2std/test-src/extensions/PtrArrayTest.cpp b/alib2std/test-src/extensions/PtrArrayTest.cpp new file mode 100644 index 0000000000000000000000000000000000000000..120cede2336b4bf3e395ae701b8256b27c897c5d --- /dev/null +++ b/alib2std/test-src/extensions/PtrArrayTest.cpp @@ -0,0 +1,43 @@ +#include "PtrArrayTest.h" +#include <alib/ptr_array> + +CPPUNIT_TEST_SUITE_NAMED_REGISTRATION( PtrArrayTest, "bits" ); +CPPUNIT_TEST_SUITE_REGISTRATION( PtrArrayTest ); + +void PtrArrayTest::setUp() { +} + +void PtrArrayTest::tearDown() { +} + +void PtrArrayTest::testProperties() { + ext::ptr_array < int, 4 > data = {1, 2, 3, 4}; + + std::cout << data [ 0 ] << std::endl; + + CPPUNIT_ASSERT ( data [ 0 ] == 1 ); + CPPUNIT_ASSERT ( data.size ( ) == 4 ); + CPPUNIT_ASSERT ( data [ 3 ] == 4 ); +} + +void PtrArrayTest::testPolymorph() { + ext::ptr_array < Base, 4 > data = ext::make_ptr_array < Base > ( Child1 ( ), Child1 ( ), Child2 ( ), Child2 ( ) ); + + CPPUNIT_ASSERT ( data.size ( ) == 4 ); + + CPPUNIT_ASSERT ( data [ 0 ].type ( ) == PtrArrayTest::Type::CHILD1 ); + CPPUNIT_ASSERT ( data [ 1 ].type ( ) == PtrArrayTest::Type::CHILD1 ); + CPPUNIT_ASSERT ( data [ 2 ].type ( ) == PtrArrayTest::Type::CHILD2 ); + CPPUNIT_ASSERT ( data [ 3 ].type ( ) == PtrArrayTest::Type::CHILD2 ); + + ext::ptr_array < Base, 4 >::const_iterator iter = data.cbegin ( ); + CPPUNIT_ASSERT ( iter->type ( ) == PtrArrayTest::Type::CHILD1 ); + ++ iter; + CPPUNIT_ASSERT ( iter->type ( ) == PtrArrayTest::Type::CHILD1 ); + ++ iter; + CPPUNIT_ASSERT ( iter->type ( ) == PtrArrayTest::Type::CHILD2 ); + ++ iter; + CPPUNIT_ASSERT ( iter->type ( ) == PtrArrayTest::Type::CHILD2 ); + ++ iter; + CPPUNIT_ASSERT ( iter == data.cend ( ) ); +} diff --git a/alib2std/test-src/extensions/PtrArrayTest.h b/alib2std/test-src/extensions/PtrArrayTest.h new file mode 100644 index 0000000000000000000000000000000000000000..0b6e330810a3f4795ed4832e0968ad3412c9d0c5 --- /dev/null +++ b/alib2std/test-src/extensions/PtrArrayTest.h @@ -0,0 +1,68 @@ +#ifndef PTR_ARRAY_TEST_H_ +#define PTR_ARRAY_TEST_H_ + +#include <cppunit/extensions/HelperMacros.h> +#include <alib/compare> + +class PtrArrayTest : public CppUnit::TestFixture +{ + CPPUNIT_TEST_SUITE( PtrArrayTest ); + CPPUNIT_TEST( testProperties ); + CPPUNIT_TEST( testPolymorph ); + CPPUNIT_TEST_SUITE_END(); + + enum class Type { + CHILD1, + CHILD2 + }; + + class Base { + public: + virtual ~Base ( ) { + } + + virtual Base * clone ( ) const = 0; + virtual Base * plunder ( ) && = 0; + + virtual Type type ( ) const = 0; + }; + + class Child1 : public Base { + public: + virtual Base * clone ( ) const { + return new Child1 ( * this ); + } + + virtual Base * plunder ( ) && { + return new Child1 ( * this ); + } + + virtual Type type ( ) const { + return Type::CHILD1; + } + }; + + class Child2 : public Base { + public: + virtual Base * clone ( ) const { + return new Child2 ( * this ); + } + + virtual Base * plunder ( ) && { + return new Child2 ( * this ); + } + + virtual Type type ( ) const { + return Type::CHILD2; + } + }; + +public: + void setUp(); + void tearDown(); + + void testProperties(); + void testPolymorph(); +}; + +#endif // PTR_ARRAY_TEST_H_