This section of the archives stores flipcode's complete Developer Toolbox collection, featuring a variety of mini-articles and source code contributions from our readers.

| Mapping Int Constants To Types & Class Members Submitted by

Here's some nasty code that maps integer constants to types and class members. It's similar to the loop unrolling code that's appeared previously in flipcode. Although it's pretty disgusting to look at, I've used it once or twice to keep seperate vertex component arrays in sync. (in this case, TestFlag would represent a bit flag for the component, like a D3D FVF constant, and the m_pData? arrays would be the seperate vertex component arrays). If you're doing a lot of operations on arrays such as these, this code makes it pretty easy to add new array members, add new functionality that affects array members, or alter their underlying types.

    class DiabolicalData
    {
        public :

            //
            //    Enums
            //

            enum TestFlag
            {
                e1        = 0x1,               //    Bit flags representing the members and their types.
                e2        = 0x2,               //    Here's the checklist to add a new member to this class:
                e3        = 0x4,               //    1) Add a value to this enum to represent the member
                e4        = 0x8,               //    2) Add the member's type to the TestTypes below
                e5        = 0x10,              //    3) Add the member to this class normally
                                               //    4) Add access code for this member in the GetArrayPtr method.

                //    No constants after here...
                eLast    = e5,                 //    Note : I've used bit flags here but normal incrementing enum values
                                               //    are possible too; just change the Unroll<TestFlag(i << 1)::???
                                               //    call in the Unroll static methods to Unroll<TestFlag(i + 1)::???
            };

            //
            //    Structs
            //

            //    Member types accessible by TestFlag value
            template <TestFlag i struct TestType    {                                           };
            struct TestType<e1                        { typedef char VType;                     };
            struct TestType<e2                        { typedef int VType;                      };
            struct TestType<e3                        { typedef float VType;                    };
            struct TestType<e4                        { typedef char * VType;                   };
            struct TestType<e5                        { typedef struct { int x,y,z; } VType;    };

        private :

            struct DiabolicalUnroller    //    Keep all the Unroll structs in here so they are publically accessible to
                                         //    each other (but we keep the mechanism as a whole private).
            {
                template <TestFlag i struct Unroll
                {
                    //
                    //    Typedefs
                    //

                    typedef TestType<i::VType UnrollType;    //    Type associated with the array matched to this flag

                    //
                    //    Static Functions
                    //

                    static __forceinline void _Clear(DiabolicalData * pData)
                    {
                        //    Sets the flagged array to point to null
                        UnrollType * * pArray = (UnrollType * *)pData-GetArrayPtr(i);

                        if (pArray)
                        {
                            *pArray = 0;
                        }
                        else
                        {
                            printf("Unroll::_Clear - Array flag %d is unsupported by GetArrayPtr\n",i);
                        }

                        Unroll<TestFlag(i << 1)::_Clear(pData);
                    }

                    static __forceinline void _Allocate(DiabolicalData * pData,const int Num)
                    {
                        //    Allocates Num entries to the flagged array
                        UnrollType * * pArray = (UnrollType * *)pData-GetArrayPtr(i);

                        if (pArray)
                        {
                            if (*pArray)
                            {
                                delete [](*pArray);
                            }
                            *pArray = new UnrollType[Num];
                        }
                        else
                        {
                            printf("Unroll::_Allocate - Array flag %d is unsupported by GetArrayPtr\n",i);
                        }

                        Unroll<TestFlag(i << 1)::_Allocate(pData,Num);
                    }

                    static __forceinline void _AllocateMarked(DiabolicalData * pData,const int Num,const int Mark)
                    {
                        //    Allocates Num entries to the flagged array if i is flagged in Mark
                        UnrollType * * pArray = (UnrollType * *)pData-GetArrayPtr(i);

                        if (pArray && ((Mark & i) != 0))
                        {
                            if (*pArray)
                            {
                                delete [](*pArray);
                            }
                            *pArray = new UnrollType[Num];
                        }
                        else
                        {
                            printf("Unroll::_AllocateMarked - Array flag %d is unsupported by GetArrayPtr\n",i);
                        }

                        Unroll<TestFlag(i << 1)::_AllocateMarked(pData,Num,Mark);
                    }

                    static __forceinline void _Deallocate(DiabolicalData * pData)
                    {
                        //    Deallocates the flagged array
                        UnrollType * * pArray = (UnrollType * *)pData-GetArrayPtr(i);

                        if (pArray)
                        {
                            delete [](*pArray);
                            *pArray = 0;
                        }
                        else
                        {
                            printf("Unroll::_Deallocate - Array flag %d is unsupported by GetArrayPtr\n",i);
                        }

                        Unroll<TestFlag(i << 1)::_Deallocate(pData);
                    }
                };

                struct Unroll<TestFlag(eLast << 1)
                {
                    //    Empty unroll struct - terminates the loop unroll
                    static __forceinline void _Clear(DiabolicalData*)                                { }
                    static __forceinline void _Allocate(DiabolicalData*,const int)                    { }
                    static __forceinline void _AllocateMarked(DiabolicalData*,const int,const int)    { }
                    static __forceinline void _Deallocate(DiabolicalData*)                            { }
                };

            };

            //
            //    Members
            //

            TestType<e1::VType *    m_pData1;        //    Bogus data
            TestType<e2::VType *    m_pData2;        //    arrays to
            TestType<e3::VType *    m_pData3;        //    test this
            TestType<e4::VType *    m_pData4;        //    disgusting
            TestType<e5::VType *    m_pData5;        //    code

        public :

            //
            //    Methods
            //

            DiabolicalData()
            {
                DiabolicalUnroller::Unroll<e1::_Clear(this);
            }

            void * * GetArrayPtr(TestFlag F)
            {
                //    Array get method - update here when adding new array members
                switch (F)
                {
                    case e1 :    return (void * *)(&m_pData1);
                    case e2 :    return (void * *)(&m_pData2);
                    case e3 :    return (void * *)(&m_pData3);
                    case e4 :    return (void * *)(&m_pData4);
                    case e5 :    return (void * *)(&m_pData5);
                };

                return 0;
            }

            //
            //    Test Functions
            //

            void AllocateAll(const int NumToAllocate)
            {
                //    Allocates NumToAllocate entries to each of the arrays
                DiabolicalUnroller::Unroll<e1::_Allocate(this,NumToAllocate);
            }

            void AllocateMarked(const int NumToAllocate,const int Mark)
            {
                //    Allocates NumToAllocate entries to each of the marked arrays
                DiabolicalUnroller::Unroll<e1::_AllocateMarked(this,NumToAllocate,Mark);
            }

            void DeallocateAll()
            {
                //    Deallocates all the arrays
                DiabolicalUnroller::Unroll<e1::_Deallocate(this);
            }

    };

The zip file viewer built into the Developer Toolbox made use of the zlib library, as well as the zlibdll source additions.

Copyright 1999-2008 (C) FLIPCODE.COM and/or the original content author(s). All rights reserved.
Please read our Terms, Conditions, and Privacy information.