一段精妙的参数检查代码

近日,分析了一小段参数范围检查的代码,有如进入伊甸园,感觉处处透露着精华。
奇妙之处在于:
1. 数据与业务分离;充分体现了高内聚、低耦合。
2. “模板嵌套”运用的炉火纯青,让人感受到抽象数据类型的强大。
3. 巧妙运用结构体、递归、枚举;让复杂的逻辑简易化。
4. 功能强大,可检查随机数、一定范围数据、特定步长数据(包含有符号与无符号数)。
希望自己在几年后也能写出这样高水平的代码。

 

#include <iostream.h>
#include <stdio.h>
#include <math.h>

//typedef int int32_t
//typedef unsigned int uint32_t
typedef char char_t;


//*******************************************************************
//控制层
//*******************************************************************

//数据类型结构体定义
struct Nil
{
  //空结构体,用于边界数据
};

//for signed irregular range(for example: -100,-77,0, 1,3,5) 
//实际是一组集合
template< int32_t value, class U>
struct SsetList
{
  enum { RET = value };
  typedef U Tail;
};

//for unsigned irregular range(for example:  1,3,5,50,100) 
template< uint32_t value, class U>
struct UsetList
{
  enum { RET = value };
  typedef U Tail;
};

//for signed continuous regular range(for example:  -3,-2,-1,0,1,2,3) 
template<int32_t startPos, int32_t stopPos, class U>
struct SscopeList
{
  enum { RET1 = startPos};
  enum { RET2 = stopPos};
  typedef U Tail;
};

//for unsigned continuous regular range(for example:  0,1,2,3,4,5,6) 
template<uint32_t startPos, uint32_t stopPos, class U>
struct UscopeList
{
  enum { RET1 = startPos};
  enum { RET2 = stopPos};
  typedef U Tail;
};

//for signed step-size regular range(use step-size 4 for example:  -8,-4,0,4,8,12) 
template< int32_t startPos, int32_t stopPos, uint32_t stepSize, class U>
struct SstepsizeList
{
  enum { RET1 = startPos};
  enum { RET2 = stopPos};
  enum { RET3 = stepSize};
  typedef U Tail;
};


//for unsigned step-size regular range(use step-size 4 for example:  0,4,8,12,16,20,24) 
template< uint32_t startPos, uint32_t stopPos, uint32_t stepSize, class U>
struct UstepsizeList
{
  enum { RET1 = startPos};
  enum { RET2 = stopPos};
  enum { RET3 = stepSize};
  typedef U Tail;
};



//范围检查结构体
template< class AllowedList > struct Allowed;

//allowed check Nil
template<>
struct Allowed<Nil>
{
  static bool check( const int32_t value )
  {
    (void)value; 
    return false;
  }
  static bool check( const uint32_t value )
  {
    (void)value;
    return false;
  } 
};

//检测随机值
template<int32_t head, class VTail >
struct Allowed< SsetList<head, VTail> >
{
  static bool check( const int32_t value )
  {
    //如果检测值与第一个范围值相等,返回;否则递归检测下一个值
    return (value == head) || Allowed< VTail >::check(value);
  }
};

template<uint32_t head, class VTail >
struct Allowed< UsetList<head, VTail> >
{
  static bool check( const uint32_t value )
  {
    return (value == head) || Allowed< VTail >::check(value);
  }
};

//*******************************************************************

template<class RangeList > struct Range;
//range check Nil
template<>
struct Range<Nil>
{
  static bool check( const int32_t value )
  {
    (void)value;
    return false;
  }
  static bool check( const uint32_t value )
  {
    (void)value;
    return false;
  }
};

//检测一定范围内值
template<int32_t start, int32_t stop, class VTail >
struct Range< SscopeList<start, stop, VTail> >
{
  static bool check( const int32_t value )
  {
    return (value >= start && value <= stop) || Range< VTail >::check(value);
  }
};

template<uint32_t start, uint32_t stop, class VTail >
struct Range< UscopeList<start, stop, VTail> >
{
  static bool check( const uint32_t value )
  {
    return (value >= start && value <= stop) || Range< VTail >::check(value);
  }
};

/*小于特定值无符号值
template<uint32_t stop, class VTail >
struct Range< UscopeList<0, stop, VTail> >
{
  static bool check( const uint32_t value )
  {
    return (value <= stop) || Range< VTail >::check(value);
  }
};
*/

//检测步长递变值
template<int32_t start, int32_t stop, uint32_t stepSize, class VTail >
struct Range< SstepsizeList<start, stop, stepSize, VTail> >
{
  static bool check( const int32_t value )
  {
    return ((value >= start &&value <= stop &&abs(value - start) % stepSize == 0) || Range< VTail >::check(value));
  }
};

template<uint32_t start, uint32_t stop, uint32_t stepSize, class VTail >
struct Range< UstepsizeList<start, stop, stepSize, VTail> >
{
  static bool check( const uint32_t value )
  {
    return (value >= start &&value <= stop &&(value - start) % stepSize == 0) || Range< VTail >::check(value);
  }
};

/*小于特定值无符号值(有步长)
template<uint32_t stop, uint32_t stepSize, class VTail >
struct Range< UstepsizeList<0, stop, stepSize, VTail> >
{
  static bool check( const uint32_t value )
  {
    return (value <= stop &&value % stepSize == 0) || Range< VTail >::check(value);
  }
};
*/
//*******************************************************************

class DataVerif
{
public:
	DataVerif():checkOk(true),pad1(0),pad2(0)
	{
	}
	virtual ~DataVerif()
	{}

	bool getStatus() const
	{
	  return checkOk;
	}
//protected:
  template <class RangeList, class AllowedList>
  void checkParam(int32_t value, const char_t* elemName)
  {
    if (checkOk) 
    {
      if (!(Range<RangeList>::check(value) || Allowed<AllowedList>::check(value)))
      {
        checkOk = false;
	    printf("[%d] Warning: Data element %s: value %d not within valid range.\n",__LINE__, elemName, value);
      }
    }
  }

  template <class RangeList, class AllowedList>
  void checkParam(uint32_t value, const char_t* elemName)
  {
    if (checkOk) 
    {
      if (!(Range<RangeList>::check(value) || Allowed<AllowedList>::check(value))) 
      {
        checkOk = false;
        printf("[%d]Warning: Data element %s: value %d not within valid range.\n",__LINE__, elemName, value);
      }
    }
  }
  
	bool checkOk; //Bool for keeping track of if checks of previous elements in struct were ok.
	uint8_t pad1;
	uint16_t pad2;
};



//*******************************************************************
//数据层
//*******************************************************************

//random data  
typedef Nil SsetListRangeList;
typedef SsetList<-8,SsetList<-4,SsetList<0,SsetList<4,SsetList<8,SsetList<9,SsetList<80,Nil > > > > > > > SsetListAllowedList;

typedef Nil UsetListRangeList;
typedef UsetList<8,UsetList<12,UsetList<16,UsetList<24,UsetList<32,UsetList<40,UsetList<80,Nil > > > > > > > UsetListAllowedList;

//注意:对于随机数,数据存储在ListAllowedList中
//      对于规则数据,数据存储在ListRangeList中
//      实际可以将2者封装在一起,还没想明白分开做的好处

//for start-stop data
typedef SscopeList<-8388608,8388352,Nil > SscopeListRangeList;
typedef Nil SscopeListAllowedList;

typedef UscopeList<0,100,Nil > UscopeListRangeList; 
typedef Nil UscopeListAllowedList;

//for specific step-size data
typedef SstepsizeList<-44,100,4, Nil> SstepsizeListRangeList;
typedef Nil SstepsizeListAllowedList;

typedef UstepsizeList<44,100,4, Nil> UstepsizeListRangeList;
typedef Nil UstepsizeListAllowedList;



DataVerif dV1;
DataVerif dV2;
DataVerif dV3;
DataVerif dV4;
DataVerif dV5;
DataVerif dV6;

#define checkSsetList(x) dV1.checkParam<SsetListRangeList,SsetListAllowedList >((x),#x)
#define checkUsetList(x) dV2.checkParam<UsetListRangeList,UsetListAllowedList >((x),#x)

#define checkSscopeList(x) dV3.checkParam<SscopeListRangeList,SscopeListAllowedList >((x),#x)
#define checkUscopeList(x) dV4.checkParam<UscopeListRangeList,UscopeListAllowedList >((x),#x)

#define checkSstepsizeList(x) dV5.checkParam<SstepsizeListRangeList,SstepsizeListAllowedList >((x),#x)
#define checkUstepsizeList(x) dV6.checkParam<UstepsizeListRangeList,UstepsizeListAllowedList >((x),#x)
//注意,为什么要把#x传进去,没想明白,好像也没什么实际意义。



//*******************************************************************
//业务层
//*******************************************************************

int main()
{
//********illegal********
	printf("below is illegal value \n");
	checkSsetList(1);
	checkUsetList(1);

	checkSscopeList(9999999);
	checkUscopeList(101);

	checkSstepsizeList(49);
	checkUstepsizeList(49);
	

//********legal*******
	printf("below is legal value \n");
	checkSsetList(-4);
	checkUsetList(12);
	
	checkSscopeList(9);
	checkUscopeList(9);
	
	checkSstepsizeList(8);
	checkUstepsizeList(48);

  return 1;
}




 

你可能感兴趣的:(一段精妙的参数检查代码)