diff --git a/eeschema/CMakeLists.txt b/eeschema/CMakeLists.txt index b369a7ab40..dc7c0c050b 100644 --- a/eeschema/CMakeLists.txt +++ b/eeschema/CMakeLists.txt @@ -138,7 +138,6 @@ set( EESCHEMA_SRCS lib_draw_item.cpp lib_export.cpp lib_field.cpp - lib_items.cpp lib_pin.cpp lib_polyline.cpp lib_rectangle.cpp diff --git a/eeschema/class_libentry.h b/eeschema/class_libentry.h index 5d33e99ebb..ef25dd4cca 100644 --- a/eeschema/class_libentry.h +++ b/eeschema/class_libentry.h @@ -34,8 +34,8 @@ #include #include #include -#include #include +#include class EDA_RECT; class LINE_READER; @@ -49,6 +49,8 @@ class LIB_FIELD; typedef std::vector LIB_ALIASES; typedef std::shared_ptr PART_SPTR; ///< shared pointer to LIB_PART typedef std::weak_ptr PART_REF; ///< weak pointer to LIB_PART +typedef MULTIVECTOR LIB_ITEMS_CONTAINER; +typedef LIB_ITEMS_CONTAINER::ITEM_PTR_VECTOR LIB_ITEMS; /* values for member .m_options */ diff --git a/eeschema/lib_collectors.cpp b/eeschema/lib_collectors.cpp index f4110800bd..88af9d8f7a 100644 --- a/eeschema/lib_collectors.cpp +++ b/eeschema/lib_collectors.cpp @@ -26,7 +26,6 @@ #include #include #include -#include const KICAD_T LIB_COLLECTOR::AllItems[] = { diff --git a/eeschema/lib_collectors.h b/eeschema/lib_collectors.h index 143c18466b..48e5099cad 100644 --- a/eeschema/lib_collectors.h +++ b/eeschema/lib_collectors.h @@ -27,13 +27,10 @@ #include -#include +#include - -class LIB_ITEMS_CONTAINER; class LIB_COLLECTOR; - class LIB_COLLECTOR_DATA { int m_unit; diff --git a/eeschema/lib_items.cpp b/eeschema/lib_items.cpp deleted file mode 100644 index 99d5c34ab3..0000000000 --- a/eeschema/lib_items.cpp +++ /dev/null @@ -1,223 +0,0 @@ -/* - * This program source code file is part of KiCad, a free EDA CAD application. - * - * Copyright 2017 CERN - * @author Maciej Suminski - * @author Bernhard Stegmaier - * - * This program 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 2 - * of the License, or (at your option) any later version. - * - * 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, you may find one here: - * http://www.gnu.org/licenses/old-licenses/gpl-2.0.html - * or you may search the http://www.gnu.org website for the version 2 license, - * or you may write to the Free Software Foundation, Inc., - * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA - */ - -#include -#include -#include -#include - - -void LIB_ITEMS_CONTAINER::push_back( LIB_ITEM* aItem ) -{ - operator[]( aItem->Type() ).push_back( aItem ); -} - - -LIB_ITEMS_CONTAINER::ITERATOR LIB_ITEMS_CONTAINER::erase( - const LIB_ITEMS_CONTAINER::ITERATOR& aIterator ) -{ - LIB_ITEMS_CONTAINER::ITERATOR it( aIterator ); - it.m_it = (*aIterator.m_parent)[ aIterator.m_curType ].erase( aIterator.m_it ); - it.validate(); - - return it; -} - - -LIB_ITEMS_CONTAINER::ITERATOR LIB_ITEMS_CONTAINER::begin( int aType ) -{ - size_t bucket = ( aType != TYPE_NOT_INIT ) ? aType : first(); - return ITERATOR( this, operator[]( bucket ).begin(), bucket, aType ); -} - - -LIB_ITEMS_CONTAINER::ITERATOR LIB_ITEMS_CONTAINER::end( int aType ) -{ - size_t bucket = ( aType != TYPE_NOT_INIT ) ? aType : last(); - return ITERATOR( this, operator[]( bucket ).end(), bucket, aType ); -} - - -LIB_ITEMS_CONTAINER::CONST_ITERATOR LIB_ITEMS_CONTAINER::begin( int aType ) const -{ - size_t bucket = ( aType != TYPE_NOT_INIT ) ? aType : first(); - return CONST_ITERATOR( this, operator[]( bucket ).begin(), bucket, aType ); -} - - -LIB_ITEMS_CONTAINER::CONST_ITERATOR LIB_ITEMS_CONTAINER::end( int aType ) const -{ - size_t bucket = ( aType != TYPE_NOT_INIT ) ? aType : last(); - return CONST_ITERATOR( this, operator[]( bucket ).end(), bucket, aType ); -} - - -size_t LIB_ITEMS_CONTAINER::size( int aType ) const -{ - if( aType != TYPE_NOT_INIT ) - { - return operator[]( aType ).size(); - } - else - { - size_t cnt = 0; - - for( int i = 0; i < TYPES_COUNT; ++i) - cnt += m_data[ i ].size(); - - return cnt; - } -} - - -bool LIB_ITEMS_CONTAINER::empty( int aType ) const -{ - return ( size( aType ) == 0 ); -} - - -void LIB_ITEMS_CONTAINER::sort() -{ - for( int i = 0; i < TYPES_COUNT; ++i ) - m_data[ i ].sort(); -} - - -void LIB_ITEMS_CONTAINER::unique() -{ - for( int i = 0; i < TYPES_COUNT; ++i ) - m_data[ i ].unique(); -} - - -LIB_ITEMS& LIB_ITEMS_CONTAINER::operator[]( int aType ) -{ - if( ( aType < FIRST_TYPE ) || ( aType > LAST_TYPE ) ) - throw std::out_of_range( "LIB_ITEMS_CONTAINER out of range" ); - - return m_data[ aType - FIRST_TYPE ]; -} - - -const LIB_ITEMS& LIB_ITEMS_CONTAINER::operator[]( int aType ) const -{ - if( ( aType < FIRST_TYPE ) || ( aType > LAST_TYPE ) ) - throw std::out_of_range( "LIB_ITEMS_CONTAINER out of range" ); - - return m_data[ aType - FIRST_TYPE ]; -} - - -size_t LIB_ITEMS_CONTAINER::first() const -{ - int i = 0; - - while( ( i < TYPES_COUNT ) && ( m_data[ i ].empty() ) ) - ++i; - - return ( i == TYPES_COUNT ) ? FIRST_TYPE : FIRST_TYPE + i; -} - - -size_t LIB_ITEMS_CONTAINER::last() const -{ - int i = TYPES_COUNT - 1; - - while( ( i >= 0 ) && ( m_data[ i ].empty() ) ) - --i; - - return ( i < 0 ) ? FIRST_TYPE : FIRST_TYPE + i; -} - - -template< typename ITEM_TYPE > -LIB_ITEMS_CONTAINER::ITERATOR_BASE& LIB_ITEMS_CONTAINER::ITERATOR_BASE::operator++() -{ - if( m_it != (*m_parent)[ m_curType ].end() ) - ++m_it; - - validate(); - - return *this; -} - - -template< typename ITEM_TYPE > -bool LIB_ITEMS_CONTAINER::ITERATOR_BASE::operator!=( - const LIB_ITEMS_CONTAINER::ITERATOR_BASE& aOther ) const -{ - if( aOther.m_parent != m_parent ) - return true; - - if( aOther.m_filter != m_filter ) - return true; - - if( aOther.m_curType != m_curType ) - return true; - - return aOther.m_it != m_it; -} - - -template< typename ITEM_TYPE > -LIB_ITEMS_CONTAINER::ITERATOR_BASE::ITERATOR_BASE( - typename LIB_ITEMS_CONTAINER::ITERATOR_ADAPTER< ITEM_TYPE >::CONTAINER* aItems, - typename LIB_ITEMS_CONTAINER::ITERATOR_ADAPTER< ITEM_TYPE >::ITERATOR aIt, - int aBucket, int aType ) - : m_parent( aItems ), m_it( aIt ), m_curType( aBucket ) -{ - m_filter = ( aType != TYPE_NOT_INIT ); -} - - -template< typename ITEM_TYPE > -void LIB_ITEMS_CONTAINER::ITERATOR_BASE::validate() -{ - // for all-items iterators (unfiltered): check if this is the end of the - // current type container, if so switch to the next non-empty container - if( !m_filter && m_it == (*m_parent)[ m_curType ].end() ) - { - // switch to the next type (look for a not empty container) - int nextType = m_curType; - - do - ++nextType; - while( ( nextType <= LAST_TYPE ) && (*m_parent)[ nextType ].empty() ); - - // there is another not empty container, so make the iterator point to it, - // otherwise it means the iterator points to the last item - if( nextType <= LAST_TYPE ) - { - m_curType = nextType; - m_it = (*m_parent)[ m_curType ].begin(); - } - } -} - -/* - * Template instantiation for const/non-const iterator - */ -template class LIB_ITEMS_CONTAINER::ITERATOR_BASE< LIB_ITEM >; -template class LIB_ITEMS_CONTAINER::ITERATOR_BASE< const LIB_ITEM >; diff --git a/eeschema/lib_items.h b/eeschema/lib_items.h deleted file mode 100644 index 7cf3e2a1a0..0000000000 --- a/eeschema/lib_items.h +++ /dev/null @@ -1,173 +0,0 @@ -/* - * This program source code file is part of KiCad, a free EDA CAD application. - * - * Copyright 2017 CERN - * @author Maciej Suminski - * @author Bernhard Stegmaier - * - * This program 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 2 - * of the License, or (at your option) any later version. - * - * 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, you may find one here: - * http://www.gnu.org/licenses/old-licenses/gpl-2.0.html - * or you may search the http://www.gnu.org website for the version 2 license, - * or you may write to the Free Software Foundation, Inc., - * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA - */ - -#ifndef LIB_ITEMS_H -#define LIB_ITEMS_H - -/** - * LIB_ITEM containers. - */ - -#include -#include - -class LIB_ITEM; - -/** - * Helper for defining a list of library draw object pointers. The Boost - * pointer containers are responsible for deleting object pointers placed - * in them. If you access a object pointer from the list, do not delete - * it directly. - */ -typedef boost::ptr_vector LIB_ITEMS; - - -/** - * LIB_ITEM container class. Provides both access as a flat list as well as - * access by type of item. - */ -class LIB_ITEMS_CONTAINER -{ -public: - /** - * Compile-time helper class to define some types depending on const/non-const iterator. - */ - template< typename ITEM_TYPE > struct ITERATOR_ADAPTER; - - /** - * Generic implementation of a flat const/non-const iterator over contained items. - */ - template< typename ITEM_TYPE > class ITERATOR_BASE - { - public: - ITERATOR_BASE& operator++(); - - ITEM_TYPE& operator*() - { - return *m_it; - } - - ITEM_TYPE* operator->() - { - return &( *m_it ); - } - - bool operator!=( const ITERATOR_BASE& aOther ) const; - - protected: - /** - * Constructor. - * @param aItems is the container to wrap. - * @param aIt is the iterator to initialize this iterator (usually some begin() or end() - * iterator). - * @param aBucket is the type ID of the given iterator. - * @param aType enables item type filtering. When aType is TYPE_NOT_INIT, there is no - * filtering and all item types are accessible by the iterator. - */ - ITERATOR_BASE( typename ITERATOR_ADAPTER::CONTAINER* aItems, - typename ITERATOR_ADAPTER::ITERATOR aIt, - int aBucket, int aType = TYPE_NOT_INIT ); - - ///> Assures the iterator is in a valid state. - void validate(); - - ///> Wrapped container - typename ITERATOR_ADAPTER::CONTAINER* m_parent; - - ///> Iterator for one of the LIB_ITEMS containers stored in the map - typename ITERATOR_ADAPTER::ITERATOR m_it; - - ///> Flag indicating whether type filtering is enabled - bool m_filter; - - ///> Type of the currently iterated items (@see KICAD_T) - int m_curType; - - friend class LIB_ITEMS_CONTAINER; - }; - - ///> The non-const iterator - typedef ITERATOR_BASE< LIB_ITEM > ITERATOR; - ///> The const iterator - typedef ITERATOR_BASE< const LIB_ITEM > CONST_ITERATOR; - - - LIB_ITEMS_CONTAINER() - { - } - - void push_back( LIB_ITEM* aItem ); - ITERATOR erase( const ITERATOR& aIterator ); - - ITERATOR begin( int aType = TYPE_NOT_INIT ); - ITERATOR end( int aType = TYPE_NOT_INIT ); - CONST_ITERATOR begin( int aType = TYPE_NOT_INIT ) const; - CONST_ITERATOR end( int aType = TYPE_NOT_INIT ) const; - - size_t size( int aType = TYPE_NOT_INIT ) const; - bool empty( int aType = TYPE_NOT_INIT ) const; - void sort(); - void unique(); - - LIB_ITEMS& operator[]( int aType ); - const LIB_ITEMS& operator[]( int aType ) const; - - // Range of valid types handled by the iterator - static constexpr KICAD_T FIRST_TYPE = LIB_ARC_T; - static constexpr KICAD_T LAST_TYPE = LIB_FIELD_T; - static constexpr size_t TYPES_COUNT = LAST_TYPE - FIRST_TYPE + 1; - -private: - ///> Get first non-empty type or first type if all are empty. - size_t first() const; - - ///> Get last non-empty type or first type if all are empty. - size_t last() const; - - ///> Contained items by type - LIB_ITEMS m_data[ TYPES_COUNT ]; -}; - -/* - * Definitions for non-const iterator - */ -template<> -struct LIB_ITEMS_CONTAINER::ITERATOR_ADAPTER< LIB_ITEM > -{ - typedef LIB_ITEMS::iterator ITERATOR; - typedef LIB_ITEMS_CONTAINER CONTAINER; -}; - -/* - * Definitions for const iterator - */ -template<> -struct LIB_ITEMS_CONTAINER::ITERATOR_ADAPTER< const LIB_ITEM > -{ - typedef LIB_ITEMS::const_iterator ITERATOR; - typedef const LIB_ITEMS_CONTAINER CONTAINER; -}; - -#endif /* LIB_ITEMS_H */ diff --git a/include/multivector.h b/include/multivector.h new file mode 100644 index 0000000000..5b1c88ed7b --- /dev/null +++ b/include/multivector.h @@ -0,0 +1,289 @@ +/* + * This program source code file is part of KiCad, a free EDA CAD application. + * + * Copyright 2017 CERN + * @author Maciej Suminski + * @author Bernhard Stegmaier + * + * This program 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 2 + * of the License, or (at your option) any later version. + * + * 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, you may find one here: + * http://www.gnu.org/licenses/old-licenses/gpl-2.0.html + * or you may search the http://www.gnu.org website for the version 2 license, + * or you may write to the Free Software Foundation, Inc., + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA + */ + +#ifndef MULTIVECTOR_H +#define MULTIVECTOR_H + +#include +#include + +/** + * Multivector container type. + * + * Keeps items segregated by their type in multiple ptr_vectors. Provides both + * access as a flat list as well as access by type of item. + * + * T is the stored type, needs to provide Type() method used to segregate items. + * FIRST_TYPE_VAL is the lower boundary value of the types stored in the container. + * LAST_TYPE_VAL is the upper boundary value of the types stored in the container. + */ +template +class MULTIVECTOR +{ +public: + /** + * Type value to indicate no specific type. Mostly used to access the container as a flat list + * or to return data for the whole container. + */ + static constexpr int UNDEFINED_TYPE = 0; + static_assert( FIRST_TYPE_VAL > UNDEFINED_TYPE, "FIRST_TYPE_VAL has to be greater than UNDEFINED_TYPE" ); + static_assert( FIRST_TYPE_VAL < LAST_TYPE_VAL, "FIRST_TYPE_VAL has to be greater than LAST_TYPE_VAL" ); + + /** + * Helper for defining a list of library draw object pointers. The Boost + * pointer containers are responsible for deleting object pointers placed + * in them. If you access a object pointer from the list, do not delete + * it directly. + */ + typedef boost::ptr_vector ITEM_PTR_VECTOR; + + /** + * Generic implementation of a flat const/non-const iterator over contained items. + */ + template + class ITERATOR_BASE + { + public: + ITEM_TYPE& operator*() + { + return *m_it; + } + + ITEM_TYPE* operator->() + { + return &( *m_it ); + } + + ITERATOR_BASE& operator++() + { + if( m_it != (*m_parent)[ m_curType ].end() ) + ++m_it; + + validate(); + + return *this; + } + + bool operator!=( const ITERATOR_BASE& aOther ) const + { + if( aOther.m_parent != m_parent ) + return true; + + if( aOther.m_filter != m_filter ) + return true; + + if( aOther.m_curType != m_curType ) + return true; + + return aOther.m_it != m_it; + } + + protected: + /** + * Constructor. + * @param aItems is the container to wrap. + * @param aIt is the iterator to initialize this iterator (usually some begin() or end() + * iterator). + * @param aBucket is the type ID of the given iterator. + * @param aType enables item type filtering. When aType is UNDEFINED_TYPE, there is no + * filtering and all item types are accessible by the iterator. + */ + ITERATOR_BASE( ITEM_CONTAINER* aItems, ITEM_CONTAINER_IT aIt, + int aBucket, int aType = UNDEFINED_TYPE ) + : m_parent( aItems ), m_it( aIt ), m_curType( aBucket ) + { + m_filter = ( aType != UNDEFINED_TYPE ); + } + + ///> Assures the iterator is in a valid state. + void validate() + { + // for all-items iterators (unfiltered): check if this is the end of the + // current type container, if so switch to the next non-empty container + if( !m_filter && m_it == (*m_parent)[ m_curType ].end() ) + { + // switch to the next type (look for a not empty container) + int nextType = m_curType; + + do + ++nextType; + while( ( nextType <= LAST_TYPE ) && (*m_parent)[ nextType ].empty() ); + + // there is another not empty container, so make the iterator point to it, + // otherwise it means the iterator points to the last item + if( nextType <= LAST_TYPE ) + { + m_curType = nextType; + m_it = (*m_parent)[ m_curType ].begin(); + } + } + } + + ///> Wrapped container + ITEM_CONTAINER* m_parent; + + ///> Iterator for one of the ptr_vector containers stored in the array + ITEM_CONTAINER_IT m_it; + + ///> Flag indicating whether type filtering is enabled + bool m_filter; + + ///> Type of the currently iterated items + int m_curType; + + friend class MULTIVECTOR; + }; + + ///> The non-const iterator + typedef ITERATOR_BASE, typename ITEM_PTR_VECTOR::iterator> ITERATOR; + ///> The const iterator + typedef ITERATOR_BASE, typename ITEM_PTR_VECTOR::const_iterator> CONST_ITERATOR; + + + MULTIVECTOR() + { + } + + void push_back( T* aItem ) + { + operator[]( aItem->Type() ).push_back( aItem ); + } + + ITERATOR erase( const ITERATOR& aIterator ) + { + ITERATOR it( aIterator ); + it.m_it = (*aIterator.m_parent)[ aIterator.m_curType ].erase( aIterator.m_it ); + it.validate(); + + return it; + } + + ITERATOR begin( int aType = UNDEFINED_TYPE ) + { + int bucket = ( aType != UNDEFINED_TYPE ) ? aType : first(); + return ITERATOR( this, operator[]( bucket ).begin(), bucket, aType ); + } + + ITERATOR end( int aType = UNDEFINED_TYPE ) + { + int bucket = ( aType != UNDEFINED_TYPE ) ? aType : last(); + return ITERATOR( this, operator[]( bucket ).end(), bucket, aType ); + } + + CONST_ITERATOR begin( int aType = UNDEFINED_TYPE ) const + { + int bucket = ( aType != UNDEFINED_TYPE ) ? aType : first(); + return CONST_ITERATOR( this, operator[]( bucket ).begin(), bucket, aType ); + } + + CONST_ITERATOR end( int aType = UNDEFINED_TYPE ) const + { + int bucket = ( aType != UNDEFINED_TYPE ) ? aType : last(); + return CONST_ITERATOR( this, operator[]( bucket ).end(), bucket, aType ); + } + + size_t size( int aType = UNDEFINED_TYPE ) + { + if( aType != UNDEFINED_TYPE ) + { + return operator[]( aType ).size(); + } + else + { + size_t cnt = 0; + + for( int i = 0; i < TYPES_COUNT; ++i) + cnt += m_data[ i ].size(); + + return cnt; + } + } + + bool empty( int aType = UNDEFINED_TYPE ) + { + return ( size( aType ) == 0 ); + } + + void sort() + { + for( int i = 0; i < TYPES_COUNT; ++i ) + m_data[ i ].sort(); + } + + void unique() + { + for( int i = 0; i < TYPES_COUNT; ++i ) + m_data[ i ].unique(); + } + + ITEM_PTR_VECTOR& operator[]( int aType ) + { + if( ( aType < FIRST_TYPE ) || ( aType > LAST_TYPE ) ) + throw std::out_of_range( "MULTIVECTOR out of range" ); + + return m_data[ aType - FIRST_TYPE ]; + } + + const ITEM_PTR_VECTOR& operator[]( int aType ) const + { + if( ( aType < FIRST_TYPE ) || ( aType > LAST_TYPE ) ) + throw std::out_of_range( "MULTIVECTOR out of range" ); + + return m_data[ aType - FIRST_TYPE ]; + } + + // Range of valid types handled by the iterator + static constexpr int FIRST_TYPE = FIRST_TYPE_VAL; + static constexpr int LAST_TYPE = LAST_TYPE_VAL; + static constexpr size_t TYPES_COUNT = LAST_TYPE - FIRST_TYPE + 1; + +private: + ///> Get first non-empty type or first type if all are empty. + int first() const + { + int i = 0; + + while( ( i < TYPES_COUNT ) && ( m_data[ i ].empty() ) ) + ++i; + + return ( i == TYPES_COUNT ) ? FIRST_TYPE : FIRST_TYPE + i; + } + + ///> Get last non-empty type or first type if all are empty. + int last() const + { + int i = TYPES_COUNT - 1; + + while( ( i >= 0 ) && ( m_data[ i ].empty() ) ) + --i; + + return ( i < 0 ) ? FIRST_TYPE : FIRST_TYPE + i; + } + + ///> Contained items by type + ITEM_PTR_VECTOR m_data[TYPES_COUNT]; +}; + +#endif /* MULTIVECTOR_H */