/////////////////////////////////////////////////////////////////////////////// // Copyright (C) 2002-2025, Open Design Alliance (the "Alliance"). // All rights reserved. // // This software and its documentation and related materials are owned by // the Alliance. The software may only be incorporated into application // programs owned by members of the Alliance, subject to a signed // Membership Agreement and Supplemental Software License Agreement with the // Alliance. The structure and organization of this software are the valuable // trade secrets of the Alliance and its suppliers. The software is also // protected by copyright law and international treaty provisions. Application // programs incorporating this software must include the following statement // with their copyright notices: // // This application incorporates Open Design Alliance software pursuant to a license // agreement with Open Design Alliance. // Open Design Alliance Copyright (C) 2002-2025 by Open Design Alliance. // All rights reserved. // // By use of this software, its documentation or related materials, you // acknowledge and accept the above terms. /////////////////////////////////////////////////////////////////////////////// #ifndef _DAI_AGGR_UTILS_H #define _DAI_AGGR_UTILS_H #include "OdPlatformSettings.h" #include "OdaCommon.h" #include "daiBuildOptions.h" #include "daiUtils/daiUnset.h" #include "daiArray.h" #include "daiList.h" #include "daiSet.h" #include "daiBag.h" #include "daiPrepareAggregateItem.h" #include "TD_PackPush.h" namespace OdDAI { //DOM-IGNORE-BEGIN template class AggrPushCommonInterface { }; template class AggrPushCommonInterface { public: /** \details Constructor for the AggrPushCommonInterface class. \param internalAggr [in] Associated ordered aggregate. */ AggrPushCommonInterface(TAggrOrdered& internalAggr) : m_internalAggr(internalAggr) , m_nextIndex(0) { } /** \details Prepares this object for a correct work. */ void prepare() { m_internalAggr.createEmpty(); if (m_internalAggr.aggrType() == aggrTypeArray) m_nextIndex = m_internalAggr.getLowerBound(); else m_nextIndex = 0; } void prepareItem(typename TAggrOrdered::value_type& valueToPush) { valueToPush = m_internalAggr.template generateAggrItem(); } /** \details Pushes the specified value. \param valueToPush [in] Associated ordered aggregate. */ bool push(const typename TAggrOrdered::value_type& valueToPush) { m_internalAggr.putByIndex(m_nextIndex, valueToPush); ++m_nextIndex; return true; } private: TAggrOrdered& m_internalAggr; unsigned int m_nextIndex; }; template class AggrPushCommonInterface { public: AggrPushCommonInterface(TAggrUnordered& internalAggr) : m_internalAggr(internalAggr) { } void prepare() { m_internalAggr.createEmpty(); } void prepareItem(typename TAggrUnordered::value_type& valueToPush) { valueToPush = m_internalAggr.template generateAggrItem(); } bool push(const typename TAggrUnordered::value_type& valueToPush) { return m_internalAggr.Add(valueToPush); } private: TAggrUnordered& m_internalAggr; }; template class ArrayPushCommonInterface { public: ArrayPushCommonInterface(OdArray& internalArray) : m_internalArray(internalArray) { } void prepare() { m_internalArray.clear(); } bool push(const TItem& valueToPush) { m_internalArray.push_back(valueToPush); return true; } private: OdArray& m_internalArray; }; template class RawPointerPushCommonInterface { public: RawPointerPushCommonInterface(TItem* begin, TItem* end) : m_begin(begin) , m_end(end) , m_current(NULL) { ODA_ASSERT(m_begin <= m_end); } void prepare() { m_current = m_begin; } bool push(const TItem& valueToPush) { if (!m_current) { return false; } bool arrayIsFinished = (m_current == m_end); *m_current = valueToPush; if (arrayIsFinished) { m_current = NULL; } else { ++m_current; } return true; } private: TItem* m_begin; TItem* m_current; TItem* m_end; }; } namespace OdDAI { /** \details Extracts the lower bound index of the specified array. \param array [in] Array from which to get the lower bound. \returns lower required index of the specified array if the array is not NULL and member count of array is greater than 0; otherwise the method returns 0. \remarks Example: " TYPE ComplexNumber: ARRAY [1:2] OF REAL; " In this case the method returns 1. */ template int extractLower(const Array& array) { return (!array.isNil() && array.getMemberCount() > 0) ? array.getLowerIndex() : 0; } /** \details Extracts the lower bound index of the specified array. \param array [in] Array from which to get the lower bound. \returns lower required index of the specified array if the array is not NULL and member count of array is greater than 0; otherwise the method returns 0. \remarks Example: " TYPE ComplexNumber: ARRAY [1:2] OF REAL; " In this case the method returns 2. */ template int extractUpper(const Array& array) { return (!array.isNil() && array.getMemberCount() > 0) ? array.getUpperIndex() + 1 : 0; } /** \details Extracts the lower bound index of the specified list. \param list [in] List from which to get the lower bound. \returns lower required index of the specified list if the list is not NULL; otherwise the method returns 0. \remarks Example: " TilingPattern : LIST [2:2] OF IfcVector; " In this case the method returns 2. */ template int extractLower(const List& list) { return !list.isNil() ? list.getLowerBound() : 0; } /** \details Extracts the lower bound index of the specified list. \param list [in] List from which to get the lower bound. \returns lower required index of the specified list if the list is not NULL; otherwise the method returns 0. \remarks Example: " TilingPattern : LIST [2:2] OF IfcVector; " In this case the method returns 2. */ template int extractUpper(const List& list) { return !list.isNil() ? list.getUpperBound() : 0; } template class AggrReadCommonInterface {}; namespace { template bool unsetReadFilter(const TType&, TAggr* aggr = nullptr) { return true; } bool unsetReadFilter(const OdDAIObjectId& value, OdDAI::Set* /*aggr*/ = nullptr) { return !OdDAI::Utils::isUnset(value); } bool unsetReadFilter(const OdDAIObjectId& value, OdDAI::List* /*aggr*/ = nullptr) { return !OdDAI::Utils::isUnset(value); } bool unsetReadFilter(const OdDAIObjectId& value, OdDAI::Bag* /*aggr*/ = nullptr) { return !OdDAI::Utils::isUnset(value); } } template class AggrReadCommonInterface { // Skips erased instances. At this moment is using at file writing functionality only. public: //typedef typename std::enable_if >::value>::type AggrOrderedType; AggrReadCommonInterface(TAggrOrdered& internalAggr) : m_internalAggr(internalAggr) , m_nextIndex(0) , m_lower(extractLower(internalAggr)) , m_upper(extractUpper(internalAggr)) { } bool isValid() { return !m_internalAggr.isNil(); } void prepare() { if (!isValid()) { return; } m_nextIndex = m_lower; } void prepareItem(typename TAggrOrdered::value_type& valueToPush) { valueToPush = m_internalAggr.template generateAggrItem(); } bool getNext(typename TAggrOrdered::value_type& valueToGet) { if (!isValid()) { return false; } bool succeeded = false; typename TAggrOrdered::value_type transitValue; prepareItem(transitValue); while (m_upper > m_nextIndex) { transitValue = m_internalAggr.template getByIndex(m_nextIndex); ++m_nextIndex; if (unsetReadFilter(transitValue, &m_internalAggr)) { valueToGet = transitValue; succeeded = true; break; } } return succeeded; } protected: private: TAggrOrdered& m_internalAggr; int m_nextIndex; const int m_lower; const int m_upper; }; template class AggrReadCommonInterface { public: AggrReadCommonInterface(TAggrUnordered& internalAggr) : m_internalAggr(internalAggr) , m_nextIterator(!internalAggr.isNil() ? internalAggr.createIterator() : NULL) { } bool isValid() { return !m_nextIterator.isNull(); } void prepare() { if (!isValid()) { return; } m_nextIterator->beginning(); } void prepareItem(typename TAggrUnordered::value_type& valueToPush) { valueToPush = m_internalAggr.template generateAggrItem(); } bool getNext(typename TAggrUnordered::value_type& valueToGet) { if (!isValid()) { return false; } typename TAggrUnordered::value_type transitValue; prepareItem(transitValue); while (m_nextIterator->next()) { #ifdef _AGGR_RETURN_PTR if ((m_nextIterator->getCurrentMemberValue() >> transitValue) == false) { continue; } #else if ((m_nextIterator->getCurrentMember() >> transitValue) == false) { continue; } #endif TAggrUnordered* templateSpecHelper = nullptr; if (!unsetReadFilter(transitValue, templateSpecHelper)) { continue; } valueToGet = transitValue; return true; } return false; } private: IteratorPtr m_nextIterator; TAggrUnordered& m_internalAggr; }; template class ArrayReadCommonInterface { public: ArrayReadCommonInterface(OdArray& internalArray) : m_internalArray(internalArray) , m_nextIndex(0) { } bool isValid() { return !m_internalArray.isEmpty(); } void prepare() { m_nextIndex = 0; } bool getNext(TItem& valueToGet) { if (m_internalArray.length() <= m_nextIndex) { return false; } valueToGet = m_internalArray[m_nextIndex]; ++m_nextIndex; return true; } private: OdArray& m_internalArray; unsigned int m_nextIndex; }; template class RawPointerReadCommonInterface { public: RawPointerReadCommonInterface(TItem* begin, TItem* end) : m_begin(begin) , m_end(end) , m_current(NULL) { ODA_ASSERT(m_begin <= m_end); } bool isValid() { return m_begin <= m_end; } void prepare() { m_current = m_begin; } bool getNext(TItem& valueToGet) { if (!m_current) { return false; } bool arrayIsFinished = m_current == m_end; valueToGet = *m_current; if (arrayIsFinished) { m_current = NULL; } else { ++m_current; } return true; } private: TItem* m_begin; TItem* m_current; TItem* m_end; }; } namespace OdDAI { template void copyFromAggrToRxValueArray(const AggrValueType& aggrFrom, OdArray& arrayTo) { if (!aggrFrom.isNil()) { const OdArray* internalArray = aggrFrom; if(!internalArray) { return; } unsigned int selectsCount = internalArray->size(); if (selectsCount > 0) { arrayTo.reserve(selectsCount); for (unsigned int selectIndex = 0; selectIndex < selectsCount; ++selectIndex) { arrayTo.push_back((*internalArray)[selectIndex]); } } } } } //DOM-IGNORE-END #include "TD_PackPop.h" #endif // _DAI_AGGR_H