See what's going on with flipcode!




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.