/* Copyright (c) 2002-2012 Croteam Ltd. This program is free software; you can redistribute it and/or modify it under the terms of version 2 of the GNU General Public License 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, write to the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. */ #ifndef SE_INCL_RELATIONS_H #define SE_INCL_RELATIONS_H #ifdef PRAGMA_ONCE #pragma once #endif #include // Object representing a link at the member of relation domain. class CRelationSrc : public CListHead { public: // implementation: // interface: // Construction/destruction. ENGINE_API CRelationSrc(void); ENGINE_API ~CRelationSrc(void); void Clear(void); }; // Object representing a link at the member of relation codomain. class CRelationDst : public CListHead { public: // implementation: // interface: // Construction/destruction. ENGINE_API CRelationDst(void); ENGINE_API ~CRelationDst(void); void Clear(void); }; // Object representing a link between a domain member and a codomain member. class CRelationLnk { public: // implementation: CRelationSrc *rl_prsSrc; // domain member CRelationDst *rl_prdDst; // codomain member CListNode rl_lnSrc; // node in list of links in domain member CListNode rl_lnDst; // node in list of links in codomain member // interface: // Construction/destruction. CRelationLnk(void); ~CRelationLnk(void); // Get the domain member of this pair. ENGINE_API CRelationSrc &GetSrc(void); // Get the codomain member of this pair. ENGINE_API CRelationDst &GetDst(void); }; // Global functions for creating relations. void ENGINE_API AddRelationPair(CRelationSrc &rsSrc, CRelationDst &rdDst); void ENGINE_API AddRelationPairTailTail(CRelationSrc &rsSrc, CRelationDst &rdDst); void ENGINE_API AddRelationPairHeadHead(CRelationSrc &rsSrc, CRelationDst &rdDst); // make 'for' construct for walking a list in domain member #define FOREACHSRCLINK(head, iter) \ for ( LISTITER(CRelationLnk, rl_lnSrc) iter(head); !iter.IsPastEnd(); iter.MoveToNext() ) // make 'for' construct for walking a list in codomain member #define FOREACHDSTLINK(head, iter) \ for ( LISTITER(CRelationLnk, rl_lnDst) iter(head); !iter.IsPastEnd(); iter.MoveToNext() ) // get a domain member related to a codomain member through a link #define DST(plink, dstclass, dstmember) \ ( (dstclass *) ( ((UBYTE *)(&(plink->GetDst()))) - _offsetof(dstclass, dstmember) ) ) // get a codomain member that a domain member is related to through a link #define SRC(plink, srcclass, srcmember) \ ( (srcclass *) ( ((UBYTE *)(&(plink->GetSrc()))) - _offsetof(srcclass, srcmember) ) ) // make 'for' construct for walking all codomain members related to a domain member #define FOREACHDSTOFSRC(srchead, dstclass, dstmember, pdst) \ FOREACHSRCLINK(srchead, pdst##_iter) { \ dstclass *pdst = DST(pdst##_iter, dstclass, dstmember); // make 'for' construct for walking all domain members related to a codomain member #define FOREACHSRCOFDST(dsthead, srcclass, srcmember, psrc) \ FOREACHDSTLINK(dsthead, psrc##_iter) { \ srcclass *psrc = SRC(psrc##_iter, srcclass, srcmember); #define ENDFOR } #endif /* include-once check. */