相见恨晚!C语言的驱动法编程详细解析(超多代码案例)
说明
1 概念提出
if(ucNum < 10){ucNumChar = ConvertToChar(ucNum);}else if(ucNum == 10){ucNumChar = 'A';}else if(ucNum == 11){ucNumChar = 'B';}else if(ucNum == 12){ucNumChar = 'C';}//... ...else if(ucNum == 35){ucNumChar = 'Z';}
CHAR aNumChars[] = {'0', '1', '2', /*3~9*/'A', 'B', 'C', /*D~Y*/'Z'};CHAR ucNumChar = aNumChars[ucNum % sizeof(aNumChars)];
CHAR ucNumChar = '0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ'[ucNum];1.1 查表方式
1.1.1 直接查找
if(0 == ucDay){ pszDayName = 'Sunday';}else if(1 == ucDay){ pszDayName = 'Monday';}//... ...else if(6 == ucDay){ pszDayName = 'Saturday';}
CHAR *paNumChars[] = {'Sunday', 'Monday', 'Tuesday', 'Wednesday', 'Thursday', 'Friday', 'Saturday'};CHAR *pszDayName = paNumChars[ucDay];1.1.2 索引查找
1.1.3 分段查找
#define MAX_GRADE_LEVEL (INT8U)5DOUBLE aRangeLimit[MAX_GRADE_LEVEL] = {50.0, 60.0, 70.0, 80.0, 100.0};CHAR *paGrades[MAX_GRADE_LEVEL] = {'Fail', 'Pass', 'Credit', 'Distinction', 'High Distinction'};
static CHAR* EvaluateGrade(DOUBLE dScore){ INT8U ucLevel = 0; for(; ucLevel < MAX_GRADE_LEVEL; ucLevel ) { if(dScore < aRangeLimit[ucLevel]) return paGrades[ucLevel]; } return paGrades[0];}typedef struct{ DOUBLE aRangeLimit; CHAR *pszGrade;}T_GRADE_MAP;
T_GRADE_MAP gGradeMap[MAX_GRADE_LEVEL] = { {50.0, 'Fail'}, {60.0, 'Pass'}, {70.0, 'Credit'}, {80.0, 'Distinction'}, {100.0, 'High Distinction'}};
static CHAR* EvaluateGrade(DOUBLE dScore){ INT8U ucLevel = 0; for(; ucLevel < MAX_GRADE_LEVEL; ucLevel ) { if(dScore < gGradeMap[ucLevel].aRangeLimit) return gGradeMap[ucLevel].pszGrade; } return gGradeMap[0].pszGrade;}1.2 实战示例
1.2.1 字符统计
INT32U aDigitCharNum[10] = {0}; /* 输入字符串中各数字字符出现的次数 */INT32U dwStrLen = strlen(szDigits);
INT32U dwStrIdx = 0;for(; dwStrIdx < dwStrLen; dwStrIdx ){ switch(szDigits[dwStrIdx]) { case '1': aDigitCharNum[0] ; break; case '2': aDigitCharNum[1] ; break; //... ... case '9': aDigitCharNum[8] ; break; }}for(; dwStrIdx < dwStrLen; dwStrIdx ){ aDigitCharNum[szDigits[dwStrIdx] - '0'] ;}1.2.2 月天校验
switch(OnuTime.Month){ case 1: case 3: case 5: case 7: case 8: case 10: case 12: if(OnuTime.Day>31 || OnuTime.Day<1) { CtcOamLog(FUNCTION_Pon,'Don't support this Day: %d(1~31)!!!\n', OnuTime.Day); retcode = S_ERROR; } break; case 2: if(((OnuTime.Year%4 == 0) && (OnuTime.Year%100 != 0)) || (OnuTime.Year%400 == 0)) { if(OnuTime.Day>29 || OnuTime.Day<1) { CtcOamLog(FUNCTION_Pon,'Don't support this Day: %d(1~29)!!!\n', OnuTime.Day); retcode = S_ERROR; } } else { if(OnuTime.Day>28 || OnuTime.Day<1) { CtcOamLog(FUNCTION_Pon,'Don't support this Day: %d(1~28)!!!\n', OnuTime.Day); retcode = S_ERROR; } } break; case 4: case 6: case 9: case 11: if(OnuTime.Day>30 || OnuTime.Day<1) { CtcOamLog(FUNCTION_Pon,'Don't support this Day: %d(1~30)!!!\n', OnuTime.Day); retcode = S_ERROR; } break; default: CtcOamLog(FUNCTION_Pon,'Don't support this Month: %d(1~12)!!!\n', OnuTime.Month); retcode = S_ERROR; break;}
#define MONTH_OF_YEAR 12 /* 一年中的月份数 *//* 闰年:能被4整除且不能被100整除,或能被400整除 */#define IS_LEAP_YEAR(year) ((((year) % 4 == 0) && ((year) % 100 != 0)) || ((year) % 400 == 0))
/* 平年中的各月天数,下标对应月份 */INT8U aDayOfCommonMonth[MONTH_OF_YEAR] = {31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31};
INT8U ucMaxDay = 0;if((OnuTime.Month == 2) && (IS_LEAP_YEAR(OnuTime.Year))) ucMaxDay = aDayOfCommonMonth[1] 1;else ucMaxDay = aDayOfCommonMonth[OnuTime.Month-1];
if((OnuTime.Day < 1) || (OnuTime.Day > ucMaxDay){ CtcOamLog(FUNCTION_Pon,'Month %d doesn't have this Day: %d(1~%d)!!!\n', OnuTime.Month, OnuTime.Day, ucMaxDay); retcode = S_ERROR;}1.2.3 名称构造
void Sub_SetServerType(INT8U *ServerType, INT16U wan_servertype){ if ((wan_servertype & 0x0001) == 0x0001) { strcat(ServerType, '_INTERNET'); } if ((wan_servertype & 0x0002) == 0x0002) { strcat(ServerType, '_TR069'); } if ((wan_servertype & 0x0004) == 0x0004) { strcat(ServerType, '_VOIP'); } if ((wan_servertype & 0x0008) == 0x0008) { strcat(ServerType, '_OTHER'); }}/* 获取var变量第bit位,编号从右至左 */#define GET_BIT(var, bit) (((var) >> (bit)) & 0x1)const CHAR* paSvrNames[] = {'_INTERNET', '_TR069', '_VOIP', '_OTHER'};const INT8U ucSvrNameNum = sizeof(paSvrNames) / sizeof(paSvrNames[0]);
VOID SetServerType(CHAR *pszSvrType, INT16U wSvrType){ INT8U ucIdx = 0; for(; ucIdx < ucSvrNameNum; ucIdx ) { if(1 == GET_BIT(wSvrType, ucIdx)) strcat(pszSvrType, paSvrNames[ucIdx]); }}1.2.4 值名解析
//值名映射表结构体定义,用于数值解析器typedef struct{INT32U dwElem; //待解析数值,通常为枚举变量CHAR* pszName; //指向数值所对应解析名字符串的指针}T_NAME_PARSER;/******************************************************************************* 函数名称: NameParser* 功能说明: 数值解析器,将给定数值转换为对应的具名字符串* 输入参数: VOID *pvMap :值名映射表数组,含T_NAME_PARSER结构体类型元素VOID指针允许用户在保持成员数目和类型不变的前提下,定制更有意义的结构体名和/或成员名。INT32U dwEntryNum :值名映射表数组条目数INT32U dwElem :待解析数值,通常为枚举变量INT8U* pszDefName :缺省具名字符串指针,可为空* 输出参数: NA* 返回值 : INT8U *: 数值所对应的具名字符串当无法解析给定数值时,若pszDefName为空,则返回数值对应的16进制格式字符串;否则返回pszDefName。******************************************************************************/INT8U *NameParser(VOID *pvMap, INT32U dwEntryNum, INT32U dwElem, INT8U* pszDefName){CHECK_SINGLE_POINTER(pvMap, 'NullPoniter');INT32U dwEntryIdx = 0;for(dwEntryIdx = 0; dwEntryIdx < dwEntryNum; dwEntryIdx ){T_NAME_PARSER *ptNameParser = (T_NAME_PARSER *)pvMap;if(dwElem == ptNameParser->dwElem){return ptNameParser->pszName;}//ANSI标准禁止对void指针进行算法操作;GNU标准则指定void*算法操作与char*一致。//若考虑移植性,可将pvMap类型改为INT8U*,或定义INT8U*局部变量指向pvMap。pvMap = sizeof(T_NAME_PARSER);}if(NULL != pszDefName){return pszDefName;}else{static INT8U szName[12] = {0}; //Max:'0xFFFFFFFF'sprintf(szName, '0x%X', dwElem);return szName;}}以下给出NameParser的简单应用示例://UNI端口类型值名映射表结构体定义typedef struct{INT32U dwPortType;INT8U* pszPortName;}T_PORT_NAME;//UNI端口类型解析器T_PORT_NAME gUniNameMap[] = {{1, 'Fe'},{3, 'Pots'},{99, 'Vuni'}};const INT32U UNI_NAM_MAP_NUM = (INT32U)(sizeof(gUniNameMap)/sizeof(T_PORT_NAME));VOID NameParserTest(VOID){INT8U ucTestIndex = 1;printf('[%s]<Test Case %u> Result: %s!\n', __FUNCTION__, ucTestIndex ,strcmp('Unknown', NameParser(gUniNameMap, UNI_NAM_MAP_NUM, 0, 'Unknown')) ? 'ERROR' : 'OK');printf('[%s]<Test Case %u> Result: %s!\n', __FUNCTION__, ucTestIndex ,strcmp('DefName', NameParser(gUniNameMap, UNI_NAM_MAP_NUM, 0, 'DefName')) ? 'ERROR' : 'OK');printf('[%s]<Test Case %u> Result: %s!\n', __FUNCTION__, ucTestIndex ,strcmp('Fe', NameParser(gUniNameMap, UNI_NAM_MAP_NUM, 1, 'Unknown')) ? 'ERROR' : 'OK');printf('[%s]<Test Case %u> Result: %s!\n', __FUNCTION__, ucTestIndex ,strcmp('Pots', NameParser(gUniNameMap, UNI_NAM_MAP_NUM, 3, 'Unknown')) ? 'ERROR' : 'OK');printf('[%s]<Test Case %u> Result: %s!\n', __FUNCTION__, ucTestIndex ,strcmp('Vuni', NameParser(gUniNameMap, UNI_NAM_MAP_NUM, 99, NULL)) ? 'ERROR' : 'OK');printf('[%s]<Test Case %u> Result: %s!\n', __FUNCTION__, ucTestIndex ,strcmp('Unknown', NameParser(gUniNameMap, UNI_NAM_MAP_NUM, 255, 'Unknown')) ? 'ERROR' : 'OK');printf('[%s]<Test Case %u> Result: %s!\n', __FUNCTION__, ucTestIndex ,strcmp('0xABCD', NameParser(gUniNameMap, UNI_NAM_MAP_NUM, 0xABCD, NULL)) ? 'ERROR' : 'OK');printf('[%s]<Test Case %u> Result: %s!\n', __FUNCTION__, ucTestIndex ,strcmp('NullPoniter', NameParser(NULL, UNI_NAM_MAP_NUM, 0xABCD, NULL)) ? 'ERROR' : 'OK');}
1.2.5 取值映射
typedef struct{ PORTSTATE loopMEState; PORTSTATE loopMIBState;}LOOPMAPSTRUCT;
static LOOPMAPSTRUCT s_CesLoop[] = { {NO_LOOP, e_ds1_looptype_noloop}, {PAYLOAD_LOOP, e_ds1_looptype_PayloadLoop}, {LINE_LOOP, e_ds1_looptype_LineLoop}, {PON_LOOP, e_ds1_looptype_OtherLoop}, {CES_LOOP, e_ds1_looptype_InwardLoop}};
PORTSTATE ConvertLoopMEStateToMIBState(PORTSTATE vPortState){ INT32U num = 0, ii;
num = ARRAY_NUM(s_CesLoop); for(ii = 0; ii < num; ii ) { if(vPortState == s_CesLoop[ii].loopMEState) return s_CesLoop[ii].loopMIBState; } return e_ds1_looptype_noloop;}/*********************************************************** 功能描述:进行二维数组映射表的一对一映射,用于参数适配* 参数说明:map -- 二维数组映射表 elemSrc -- 映射源,即待映射的元素值 elemDest -- 映射源对应的映射结果 direction -- 映射方向字节,表示从数组哪列映射至哪列。 高4位对应映射源列,低4位对应映射结果列。 defaultVal -- 映射失败时置映射结果为缺省值* 示例:ARRAY_MAPPER(gCesLoopMap, 3, ucLoop, 0x10, NO_LOOP); 则ucLoop = 2(LINE_LOOP)**********************************************************/#define ARRAY_MAPPER(map, elemSrc, elemDest, direction, defaultVal) do{\ INT8U ucMapIdx = 0, ucMapNum = 0; \ ucMapNum = sizeof(map)/sizeof(map[0]); \ for(ucMapIdx = 0; ucMapIdx < ucMapNum; ucMapIdx ) \ { \ if((elemSrc) == map[ucMapIdx][((direction)&0xF0)>>4]) \ { \ elemDest = map[ucMapIdx][(direction)&0x0F]; \ break; \ } \ } \ if(ucMapIdx == ucMapNum) \ { \ elemDest = (defaultVal); \ } \}while(0)static INT8U gCesLoopMap[][2] = { {NO_LOOP, e_ds1_looptype_noloop}, {PAYLOAD_LOOP, e_ds1_looptype_PayloadLoop}, {LINE_LOOP, e_ds1_looptype_LineLoop}, {PON_LOOP, e_ds1_looptype_OtherLoop}, {CES_LOOP, e_ds1_looptype_InwardLoop}};
ARRAY_MAPPER(gCesLoopMap, tPara.dwParaVal[0], dwLoopConf, 0x01, e_ds1_looptype_noloop);另举一例:
#define CES_DEFAULT_JITTERBUF (INT32U)2000 /* 默认jitterbuf为2000us,而1帧=125us */#define CES_JITTERBUF_STEP (INT32U)125 /* jitterbuf步长为125us,即1帧 */#define CES_DEFAULT_QUEUESIZE (INT32U)5#define CES_DEFAULT_MAX_QUEUESIZE (INT32U)7
#define ARRAY_NUM(array) (sizeof(array) / sizeof((array)[0])) /* 数组元素个数 */typedef struct{ INT32U dwJitterBuffer; INT32U dwFramePerPkt; INT32U dwQueueSize;}QUEUE_SIZE_MAP;/* gCesQueueSizeMap也可以(JitterBuffer / FramePerPkt)值为索引,更加紧凑 */static QUEUE_SIZE_MAP gCesQueueSizeMap[]= { {1,1,1}, {1,2,1}, {2,1,2}, {2,2,1}, {3,1,3}, {3,2,1}, {4,1,3}, {4,2,1}, {5,1,4}, {5,2,3}, {6,1,4}, {6,2,3}, {7,1,4}, {7,2,3}, {8,1,4}, {8,2,3}, {9,1,5}, {9,2,4}, {10,1,5}, {10,2,4}, {11,1,5}, {11,2,4}, {12,1,5}, {12,2,4}, {13,1,5}, {13,2,4}, {14,1,5}, {14,2,4}, {15,1,5}, {15,2,4}, {16,1,5}, {16,2,4}, {17,1,6}, {17,2,5}, {18,1,6}, {18,2,5}, {19,1,6}, {19,2,5}, {20,1,6}, {20,2,5}, {21,1,6}, {21,2,5}, {22,1,6}, {22,2,5}, {23,1,6}, {23,2,5}, {24,1,6}, {24,2,5}, {25,1,6}, {25,2,5}, {26,1,6}, {26,2,5}, {27,1,6}, {27,2,5}, {28,1,6}, {28,2,5}, {29,1,6}, {29,2,5}, {30,1,6}, {30,2,5}, {31,1,6}, {31,2,5}, {32,1,6}, {32,2,5}};/*********************************************************** 函数名称:CalcQueueSize* 功能描述:根据JitterBuffer和FramePerPkt计算QueueSize* 注意事项:配置的最大缓存深度* = 2 * JitterBuffer / FramePerPkt* = 2 * N Packet = 2 ^ QueueSize* JitterBuffer为125us帧速率的倍数,* FramePerPkt为每个分组的帧数,* QueueSize向上取整,最大为7。**********************************************************/INT32U CalcQueueSize(INT32U dwJitterBuffer, INT32U dwFramePerPkt){ INT8U ucIdx = 0, ucNum = 0;
//本函数暂时仅考虑E1 ucNum = ARRAY_NUM(gCesQueueSizeMap); for(ucIdx = 0; ucIdx < ucNum; ucIdx ) { if((dwJitterBuffer == gCesQueueSizeMap[ucIdx].dwJitterBuffer) && (dwFramePerPkt == gCesQueueSizeMap[ucIdx].dwFramePerPkt)) { return gCesQueueSizeMap[ucIdx].dwQueueSize; } }
return CES_DEFAULT_MAX_QUEUESIZE;}1.2.6 版本控制
pstSendTlv->ucLength = 0x1f;if (gOamCtrlCode == 0){ vosMemCpy(pstSendTlv->aucVersionList, ctc_oui, 3); pstSendTlv->aucVersionList[3] = 0x30; vosMemCpy(&(pstSendTlv->aucVersionList[4]), ctc_oui, 3); pstSendTlv->aucVersionList[7] = 0x21; vosMemCpy(&(pstSendTlv->aucVersionList[8]), ctc_oui, 3); pstSendTlv->aucVersionList[11] = 0x20; vosMemCpy(&(pstSendTlv->aucVersionList[12]), ctc_oui, 3); pstSendTlv->aucVersionList[15] = 0x13; vosMemCpy(&(pstSendTlv->aucVersionList[16]), ctc_oui, 3); pstSendTlv->aucVersionList[19] = 0x01; vosMemCpy(&(pstSendTlv->aucVersionList[20]), ctc_oui, 3); pstSendTlv->aucVersionList[23] = 0xaa;}else if (gOamCtrlCode == 1){ vosMemCpy(pstSendTlv->aucVersionList, ctc_oui, 3); pstSendTlv->aucVersionList[3] = 0x30; vosMemCpy(&(pstSendTlv->aucVersionList[4]), ctc_oui, 3); pstSendTlv->aucVersionList[7] = 0x21; vosMemCpy(&(pstSendTlv->aucVersionList[8]), ctc_oui, 3); pstSendTlv->aucVersionList[11] = 0x20; vosMemCpy(&(pstSendTlv->aucVersionList[12]), ctc_oui, 3); pstSendTlv->aucVersionList[15] = 0x13; vosMemCpy(&(pstSendTlv->aucVersionList[16]), ctc_oui, 3); pstSendTlv->aucVersionList[19] = 0x01;}//此处省略gOamCtrlCode == 2~6的处理代码else if (gOamCtrlCode == 7){ vosMemCpy(&(pstSendTlv->aucVersionList), ctc_oui, 3); pstSendTlv->aucVersionList[3] = 0x20; vosMemCpy(&(pstSendTlv->aucVersionList[4]), ctc_oui, 3); pstSendTlv->aucVersionList[7] = 0x13; vosMemCpy(&(pstSendTlv->aucVersionList[8]), ctc_oui, 3); pstSendTlv->aucVersionList[11] = 0x01;}
/*********************************************************************** 版本控制字数组定义* gOamCtrlCode: Bitmap控制字。Bit-X为0时上报对应版本,Bit-X为1时屏蔽对应版本。* CTRL_VERS_NUM: 可控版本个数。* CTRL_CODE_NUM: 控制字个数。与CTRL_VERS_NUM有关。* gOamVerCtrlMap: 版本控制字数组。行对应控制字,列对应可控版本。 元素值为0时不上报对应版本,元素值非0时上报该元素值。* Note: 该数组旨在实现“数据与控制隔离”。后续若要新增可控版本,只需修改 -- CTRL_VERS_NUM -- gOamVerCtrlMap新增行(控制字) -- gOamVerCtrlMap新增列(可控版本)**********************************************************************/#define CTRL_VERS_NUM 3#define CTRL_CODE_NUM (1<<CTRL_VERS_NUM)u8_t gOamVerCtrlMap[CTRL_CODE_NUM][CTRL_VERS_NUM] = { /* Ver21 Ver30 VerAA */ {0x21, 0x30, 0xaa}, /*gOamCtrlCode = 0*/ {0x21, 0x30, 0 }, /*gOamCtrlCode = 1*/ {0x21, 0, 0xaa}, /*gOamCtrlCode = 2*/ {0x21, 0, 0 }, /*gOamCtrlCode = 3*/ { 0, 0x30, 0xaa}, /*gOamCtrlCode = 4*/ { 0, 0x30, 0 }, /*gOamCtrlCode = 5*/ { 0, 0, 0xaa}, /*gOamCtrlCode = 6*/ { 0, 0, 0 } /*gOamCtrlCode = 7*/};#define INFO_TYPE_VERS_LEN 7 /* InfoType Length OUI ExtSupport Version */
u8_t verIdx = 0;u8_t index = 0;for(verIdx = 0; verIdx < CTRL_VERS_NUM; verIdx ){ if(gOamVerCtrlMap[gOamCtrlCode][verIdx] != 0) { vosMemCpy(&pstSendTlv->aucVersionList[index], ctc_oui, 3); index = 3; pstSendTlv->aucVersionList[index ] = gOamVerCtrlMap[gOamCtrlCode][verIdx]; }}vosMemCpy(&pstSendTlv->aucVersionList[index], ctc_oui, 3);index = 3;pstSendTlv->aucVersionList[index ] = 0x20;vosMemCpy(&pstSendTlv->aucVersionList[index], ctc_oui, 3);index = 3;pstSendTlv->aucVersionList[index ] = 0x13;vosMemCpy(&pstSendTlv->aucVersionList[index], ctc_oui, 3);index = 3;pstSendTlv->aucVersionList[index ] = 0x01;
pstSendTlv->ucLength = INFO_TYPE_VERS_LEN index;1.2.7 消息处理
void logall(void){ g_log_control[0] = 0xFFFFFFFF;}
void noanylog(void){ g_log_control[0] = 0;}
void logOam(void){ g_log_control[0] |= (0x01 << FUNCTION_Oam);}void nologOam(void){ g_log_control[0] &= ~(0x01 << FUNCTION_Oam);}//... ...void logExec(char *name, INT8U enable){ CtcOamLog(FUNCTION_Oam,'log %s %d\n',name,enable); if (enable == 1) /*log*/ { if (strcasecmp(name,'all') == 0) { /*字符串比较,不区分大小写*/ logall(); } else if (strcasecmp(name,'oam') == 0) { logOam(); } else if (strcasecmp(name,'pon') == 0) { logPon(); //... ... } else if (strcasecmp(name,'version') == 0) { logVersion(); } else if (enable == 0) /*nolog*/ { if (strcasecmp(name,'all') == 0) { noanylog(); } else if (strcasecmp(name,'oam') == 0) { nologOam(); } else if (strcasecmp(name,'pon') == 0) { nologPon(); //... ... } else if (strcasecmp(name,'version') == 0) { nologVersion(); } else { printf('bad log para\n'); }}typedef struct{ OAM_LOG_OFF = (INT8U)0, OAM_LOG_ON = (INT8U)1}E_OAM_LOG_MODE;typedef FUNC_STATUS (*OamLogHandler)(VOID);typedef struct{ CHAR *pszLogCls; /* 打印级别 */ E_OAM_LOG_MODE eLogMode; /* 打印模式 */ OamLogHandler fnLogHandler; /* 打印函数 */}T_OAM_LOG_MAP;
T_OAM_LOG_MAP gOamLogMap[] = { {'all', OAM_LOG_OFF, noanylog}, {'oam', OAM_LOG_OFF, nologOam}, //... ... {'version', OAM_LOG_OFF, nologVersion},
{'all', OAM_LOG_ON, logall}, {'oam', OAM_LOG_ON, logOam}, //... ... {'version', OAM_LOG_ON, logVersion}};INT32U gOamLogMapNum = sizeof(gOamLogMap) / sizeof(T_OAM_LOG_MAP);
VOID logExec(CHAR *pszName, INT8U ucSwitch){ INT8U ucIdx = 0; for(; ucIdx < gOamLogMapNum; ucIdx ) { if((ucSwitch == gOamLogMap[ucIdx].eLogMode) && (!strcasecmp(pszName, gOamLogMap[ucIdx].pszLogCls)); { gOamLogMap[ucIdx].fnLogHandler(); return; } } if(ucIdx == gOamLogMapNum) { printf('Unknown LogClass(%s) or LogMode(%d)!\n', pszName, ucSwitch); return; }}/* 日志控制类型定义 */typedef enum{ LOG_NORM = 0, /* 未分类日志,可用于通用日志 */ LOG_FRM, /* Frame,OMCI帧日志 */ LOG_PON, /* Pon,光链路相关日志 */ LOG_ETH, /* Ethernet,Layer2以太网日志 */ LOG_NET, /* Internet,Layer3网络日志 */ LOG_MULT, /* Multicast,组播日志 */ LOG_QOS, /* QOS,流量日志 */ LOG_CES, /* Ces,TDM电路仿真日志 */ LOG_VOIP, /* Voip,语音日志 */ LOG_ALM, /* Alarm,告警日志 */ LOG_PERF, /* Performance,性能统计日志 */ LOG_VER, /* Version,软件升级日志 */ LOG_XDSL, /* xDsl日志 */ LOG_DB, /* 数据库操作日志 */ //新日志类型在此处扩展,共支持32种日志类型 LOG_ALL = UINT_MAX /* 所有日志类型 */}E_LOG_TYPE;
/***************************************************************************** * 变量名称:gOmciLogCtrl * 作用描述:OMCI日志控制字,BitMap格式(比特编号从LSB至MSB依次为Bit0->BitN)。 * Bit0~N分别对应E_LOG_TYPE各枚举值(除LOG_ALL外)。 * BitX为0时关闭日志类型对应的日志功能,BitX为1时则予以打开。 * 变量范围:该变量为四字节整型静态全局变量,即支持32种日志类型。 * 访问说明:通过GetOmciLogCtrl/SetOmciLogCtrl/OmciLogCtrl函数访问/设置控制字。 *****************************************************************************/static INT32U gOmciLogCtrl = 0;
//日志类型字符串数组,下标为各字符串所对应的日志类型枚举值。static const INT8U* paLogTypeName[] = { 'Norm', 'Frame', 'Pon', 'Ethernet', 'Internet', 'Multicast', 'Qos', 'Ces', 'Voip', 'Alarm', 'Performance', 'Version', 'Xdsl', 'Db'};static const INT8U ucLogTypeNameNum = sizeof(paLogTypeName) / sizeof(paLogTypeName[0]);
static VOID SetGlobalLogCtrl(E_LOG_TYPE eLogType, INT8U ucLogSwitch){ if(LOG_ON == ucLogSwitch) gOmciLogCtrl = LOG_ALL; else gOmciLogCtrl = 0;}static VOID SetSpecificLogCtrl(E_LOG_TYPE eLogType, INT8U ucLogSwitch){ if(LOG_ON == ucLogSwitch) SET_BIT(gOmciLogCtrl, eLogType); else CLR_BIT(gOmciLogCtrl, eLogType);}
VOID OmciLogCtrl(CHAR *pszLogType, INT8U ucLogSwitch){ if(0 == strncasecmp(pszLogType, 'All', LOG_TYPE_CMP_LEN)) { SetGlobalLogCtrl(LOG_ALL, ucLogSwitch); return; }
INT8U ucIdx = 0; for(ucIdx = 0; ucIdx < ucLogTypeNameNum; ucIdx ) { if(0 == strncasecmp(pszLogType, paLogTypeName[ucIdx], LOG_TYPE_CMP_LEN)) { SetSpecificLogCtrl(ucIdx, ucLogSwitch); printf('LogType: %s, LogSwitch: %s\n', paLogTypeName[ucIdx], (1==ucLogSwitch)?'On':'Off'); return; } }
OmciLogHelp();}2 编程思想
分离原则:策略同机制分离,接口同引擎分离
表示原则:把知识叠入数据以求逻辑质朴而健壮
3 附录
3.1 网友观点
编程和人的关系
3.2 函数指针
int max(int x, int y) { return x>y?x:y; }int min(int x, int y) { return x<y?x:y; }int add(int x, int y) { return x y; }而处理函数却定义为:int process(int x, int y, int (*f)()) { return (*f)(x, y); }其中,第三个参数是一个没有参数且返回int型变量的函数指针。但后面却用process(a,b,max)的方式进行调用,max带有两个参数。若编译器未检查出错误,而又不小心将return (*f)(x,y);写成return (*f)(x);,那么后果可能很严重。因此在C语言中使用函数指针时,一定要小心'类型陷阱'。
来源:https://www.cnblogs.com/clover-toeic/p/3730362.html
赞 (0)
