⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 pack.c

📁 CBS(小区广播)程序实现手稿
💻 C
📖 第 1 页 / 共 5 页
字号:

	count_of_VPart=0;
    count_of_OPart=0;
    pos_V[0]=0;
	pos_O[0]=0;

	for (i=0;i<format_len;i++)			//计算格式串中 V O 的个数
    {
		c=format[i];
		if (c=='V' || c=='v')
			pos_V[count_of_VPart++]=i;	//记录V在格式串中的位置
		else
		if (c=='O' || c=='o')
			pos_O[count_of_OPart++]=i;	//记录O在格式串中的位置
    }

    if(pos_O[0])
		pos_V[count_of_VPart]=pos_O[0];
    else 
		pos_V[count_of_VPart]=i;		//置最后一个V类描述符在格式串中的位置
	pos_O[count_of_OPart]=i;			//置最后一个O类描述符在格式串中的位置
    Ooffset=(count_of_OPart==0) ? 0 : 1;//标志是否有O类描述符

    len=SubCommonSubFlatPack(buf,format,pos_V[0],p,finish);//调用上层函数处理F类描述符
    k=0;
    if (count_of_VPart)					//若有V类描述符则处理之
	{
		if(flag)						//若有L描述符,则按两字节填写
			for(j=0;j<count_of_VPart;j++)
			{
				(int)p=finish[0];
				temp=k+(count_of_VPart+Ooffset-j)*2;		//计算偏移地址
				memcpy(&buf[len+j*2],&temp,2);				//填入两字节中
															//调用处理F类描述符的程序对之进行处理
				m=SubCommonSubFlatPack(buf+len+(count_of_VPart+Ooffset)*2+k+2,
					format+pos_V[j]+1,pos_V[j+1]-pos_V[j],p,finish);
				memcpy(&buf[len+(count_of_VPart+Ooffset)*2+k],&m,2);		//填入V部分的长度
				k+=m+2;
			}
		else
			for (j=0;j<count_of_VPart;j++)
			{
				(int)p=finish[0];			//取得编程数据地址
				buf[len+j]=k+count_of_VPart+Ooffset-j;		//填入指向V部分的指针
															//调用处理F类描述符的程序对之进行处理
				m=SubCommonSubFlatPack(buf+len+count_of_VPart+Ooffset+k+1,
					format+pos_V[j]+1,pos_V[j+1]-pos_V[j],p,finish);
				buf[len+count_of_VPart+Ooffset+k]=m;			//填入V部分的长度
				k+=m+1;
			}
	}
    if (count_of_OPart)					//若有O类描述符则处理之
	{							
		if(flag)
		{								//置指向O部分的指针
			buf[len+count_of_VPart*2]=(pos_O[1]-pos_O[0]<3) ? 0 :k+2;
			buf[len+count_of_VPart*2+1]=(pos_O[1]-pos_O[0]<3) ? 0 :((k+2)>>8);
			for (j=0;j<count_of_OPart;j++)
			{
			(int)p=finish[0];				//取得编程数据地址	
			if (pos_O[j+1]-pos_O[j]>=3)		//如两O之间有描述符,则进行如下处理
			{
			    buf[len+(count_of_VPart+Ooffset)*2+k]=*p++;			//填入O部分的名称
																//调用处理F类描述符的程序对之进行处理
				m=SubCommonSubFlatPack(buf+len+(count_of_VPart+Ooffset)*2+k+3,
					format+pos_O[j]+1,pos_O[j+1]-pos_O[j],p,finish);
				memcpy(&buf[len+(count_of_VPart+Ooffset)*2+k+1],&m,2);	//填入O部分的长度
			    k+=m+3;
			}
			else							//如两O之间无描述符,则相应位置置零
			{
				memset(&buf[len+(count_of_VPart+Ooffset)*2+k],0,3);		
				k+=3;
			}
			}
		}
		else
		{
										//置指向O部分的指针
			buf[len+count_of_VPart]=(pos_O[1]-pos_O[0]<3) ? 0 : k+1;
			for (j=0;j<count_of_OPart;j++)
			{
			(int)p=finish[0];				//取得编程数据地址	
			if (pos_O[j+1]-pos_O[j]>=3)		//如两O之间有描述符,则进行如下处理
			{
			    buf[len+count_of_VPart+Ooffset+k]=*p++;			//填入O部分的名称
																//调用处理F类描述符的程序对之进行处理
				m=SubCommonSubFlatPack(buf+len+count_of_VPart+Ooffset+k+2,
					format+pos_O[j]+1,pos_O[j+1]-pos_O[j],p,finish);
			    buf[len+count_of_VPart+Ooffset+k+1]=m;			//填入O部分的长度
			    k+=m+2;
			}
			else							//如两O之间无描述符,则相应位置置零
			{
				buf[len+count_of_VPart+Ooffset+k]=0;
				buf[len+count_of_VPart+Ooffset+k+1]=0;
				k+=2;
			}
			}
		}
	}
		
	if(flag)	
	   return len+(count_of_VPart+Ooffset)*2+k;//返回打入的协议数据字节数
	else
	return len+count_of_VPart+Ooffset+k;
}

//*******************************************************
//				 一次性打包函数							*
// buf->协议数据区,format->格式串, para->编程数据区	*
//*******************************************************
int FlatPack(BYTE * buf,BYTE * format,...)
{
    int x;
    return CommonSubFlatPack(buf,format,strlen(format),((int *)&format)+1,&x);
}

int show(BYTE * buf,int len)
{
	int i,j;
	for (i=0;i<len;i++)
	{
		j=buf[i];
		j=j>>4;
		if(j>9) j+=7;
		j+='0';
		putchar(j);
		j=buf[i];
		j&=0x0f;
		if(j>9) j+=7;
		j+='0';
		putchar(j);
		putchar(',');
	}
	return 0;
}


//***************************************
//		一次性解包函数FlatUnPack		*
//***************************************
//***************************************
//			底层函数					*
// 实现 宽度,位序,压缩 描述符			*
// flag_RS--位序,flag_pack--压缩		*
// buf->协议数据区,s->编程数据区		*
//返回值 失败:0  成功:协议数据区宽度	*
//***************************************
int SubUnPackIt(BYTE * buf,BYTE * s,int width,int flag_RS,int flag_pack)
{
    int i,j,k,awidth,temp,temp1;

										//对一些特殊宽度进行处理
	if(width==-1) return 0;				//如由n描述符读入的宽度<=0,则返回0
	else if(width==0)
		width=1;						//如由数字读入的宽度==0,则将宽度定为1
				
    if (flag_pack==0)					//若无压缩描述符,处理如下
    {
		switch(flag_RS)					//根据不同的位序描述符进行处理
		{
			case 0:						//无位序描述符
				memcpy(s,buf,width);	
				return width;
			case 1:
				for (i=0,j=width-1;i<width;i++,j--) s[i]=buf[j];	// 整串反序
				return width;
			case 2:													// 单字反序
				for (i=0;i<width;i=i+2)
					for (k=i,j=i+1;k<i+2;k++,j--) s[k]=buf[j];
				return width;
			case 3:													// 双字反序	
				for (i=0;i<width;i=i+4)
					for (k=i,j=i+3;k<i+4;k++,j--) s[k]=buf[j];
				return width;
			case 4:													// 四字反序
				for (i=0;i<width;i=i+8)
					for (k=i,j=i+7;k<i+8;k++,j--) s[k]=buf[j];
				return width;
			default: 
				return width;
		}
    }
	if(flag_pack==1)					//#压缩描述符,处理如下
	{
		awidth=(width+1)/2;				//调整协议数据区宽度
		switch(flag_RS)					//先进行位序描述符处理
		{
			case 0:						//无位序描述符
				memcpy(s,buf,awidth);
				break;
			case 1:
				for (i=0,j=awidth-1;i<awidth;i++,j--) s[i]=buf[j];	// 整串反序
				break;
			case 2:													// 单字反序
				for (i=0;i<awidth;i=i+2)
					for (k=i,j=i+1;k<i+2;k++,j--) s[k]=buf[j];
				break;
			case 3:													// 双字反序	
				for (i=0;i<awidth;i=i+4)
					for (k=i,j=i+3;k<i+4;k++,j--) s[k]=buf[j];
				break;
			case 4:													// 四字反序
				for (i=0;i<awidth;i=i+8)
					for (k=i,j=i+7;k<i+8;k++,j--) s[k]=buf[j];
				break;
			default: 
				break;
		}
		if(width%2!=0)								//对奇数比特进行解压缩
		{
			i=awidth-1;j=i+i;
			s[j]=s[i]&0x0f;
			for(i--,j=i+i;i>=0;i--,j-=2)
			{
				temp=temp1=s[i];
				s[j]=temp&0x0f;
				s[j+1]=temp1>>4;
			}
		}
		else
			for (i=(awidth-1),j=i+i;i>=0;i--,j-=2)	//再进行解压缩				
			{
				temp=temp1=s[i];
				s[j]=temp&0x0f;
				s[j+1]=temp1>>4;
			}
		return awidth;								//返回解出的协议字节数
	}
	if(flag_pack==2)								//$压缩描述符,处理如下
	{
		awidth=(width+1)/2;							//调整协议数据区宽度
		switch(flag_RS)								//先进行位序描述符处理
		{
			case 0:									//无位序描述符
				memcpy(s,buf,width);
				break;
			case 1:
				for (i=0,j=awidth-1;i<awidth;i++,j--) s[i]=buf[j];	// 整串反序
				break;
			case 2:													// 单字反序
				for (i=0;i<awidth;i=i+2)
					for (k=i,j=i+1;k<i+2;k++,j--) s[k]=buf[j];
				break;
			case 3:													// 双字反序	
				for (i=0;i<awidth;i=i+4)
					for (k=i,j=i+3;k<i+4;k++,j--) s[k]=buf[j];
				break;
			case 4:													// 四字反序
				for (i=0;i<awidth;i=i+8)
					for (k=i,j=i+7;k<i+8;k++,j--) s[k]=buf[j];
				break;
			default: 
				break;
		}
		if(width%2!=0)								//对奇数比特进行解压缩
		{
			i=awidth-1;j=i+i;
			s[j]=s[i]>>4;
			for(i--,j=i+i;i>=0;i--,j-=2)
			{
				temp=temp1=s[i];
				s[j]=temp1>>0x0f;
				s[j+1]=temp&0x0f;
			}
		}
		else
			for (i=(awidth-1),j=i*2;i>=0;i--,j-=2)	//再进行解压缩
			{
				temp=temp1=s[i];
				s[j]=temp1>>4;
				s[j+1]=temp&0x0f;
			}
		return awidth;								//返回解出的协议字节数
	}
    return 0;
}

//***************************************
//		实现F类描述符					*
// buf->协议数据区,p->编程数据区		*
// finish[] 记录格式串位置				*
//***************************************
int SubCommonSubUnFlatPack(BYTE * buf,BYTE * format,int format_len,
	int p[],int finish[])
{
    int    i,len,width,state,flag_RS,flag_pack,flag;
    int	   offset;
	BYTE   c,*pb,p1,p2;
	DWORD j,temp,*k;

    len=0;								//为各计数变量赋处值
    width=0;
    flag_RS=0;
    flag_pack=0;
    for (i=0;i<format_len;i++)			//对格式串按给定长度进行一遍扫描
    switch(c=format[i])
    {
	case '0':
	case '1':
	case '2':
	case '3':
	case '4':
	case '5':
	case '6':
	case '7':
	case '8':
	case '9':
		c-='0';
		width=width*10+c;				//计算宽度
		break;

	case 'n':
	case 'N':
		width=*p++;
		if(width<=0) width=-1;			//如由n描述符读入的宽度<=0
										//则将宽度定为-1,否则不变
		break;

	case 'r':
		flag_RS=1;
		break;

	case 'R':
		flag_RS=2;
		break;

	case 's':				
		flag_RS=3;
		break;

	case 'S':							//记录位序描述符
		flag_RS=4;
		break;

	case '#':
		flag_pack=1;
		break;

	case '$':							//记录压缩描述符
		flag_pack=2;
		break;

	case 'f':							//遇F类描述符即调用上层函数处理格式串
	case 'F':
		len+=SubUnPackIt(buf+len,(BYTE *)*p,width,flag_RS,flag_pack);
		p++;							//P指针后移
		width=0;						//重置各计数变量
		flag_RS=0;
		flag_pack=0;
		break;

						//遇比特描述符立即处理格式串用两个变量记录比特描述符的
	case 'b':			//大小写与宽度 state:宽度,flag:大小写	
	case 'B':							
		state=1;						
		flag=0;							
		goto l;

	case 'w':
		state=2;
		flag=0;
		goto l;
	
	case 'd':
		state=4;
		flag=0;
		goto l;

	case 'W':
		state=2;
		flag=1;
		goto l;

	case 'D':
		state=4;
		flag=1;
		goto l;

	default:
		break;

l:
	i++;								
	while(format[i]==' '&&format[i]!='\0')	//移动指针,跳过空格
		i++;

	k=(DWORD*)(buf+len);					//先从协议数据中提取4个字节
	temp=*k;								//将temp中变量调整到Intel格式
	if(flag)								
	{
		switch(state)						//如描述符是W,则将temp变量的						
		{									//前两个字节互换位子
		case 2:
			j=temp;
			j>>=8;
			j&=0xff;
			temp<<=8;
			temp|=j;
			break;
		case 4:								//如描述符是D,则将temp变量的
			pb=(BYTE*)&temp;					//第一 第四字节互换位子
			p1=pb[0];						//第二 第三字节互换位子
			p2=pb[3];
			pb[0]=p2;
			pb[3]=p1;
			p1=pb[1];
			p2=pb[2];
			pb[1]=p2;
			pb[2]=p1;
			break;
		default:
			break;
		}
	}

	if(format[i]=='\0'||format[i]!='(')		//若比特描述符为单个 直接将
	{										//协议数据写入变量
		offset=state*8;						//计算需屏蔽的位数
		*(int*)p[0]>>=offset;				//屏蔽编程数据的某几位
		*(int*)p[0]<<=offset;
		j=temp;
		j<<=(32-offset);
		j>>=(32-offset);
		*(int*)p[0]|=(int)j;				//将协议数据的比特位按要求赋给编程数据
		p++;
	}

	else									//否则按(...)中的描述符处理
	{
		offset=0;										//将各变量置处值
		for(;format[i-1]!=')'&&i<format_len;i++)		//若格式串不遇')' or 不超规定
			switch (c=format[i])						//长度则继续扫描
			{
			case '0':
			case '1':
			case '2':
			case '3':
			case '4':
			case '5':
			case '6':

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -