无我

让内心永远燃烧着伟大的光明的精神之火!
灵活的思考,严谨的实现
豪迈的气魄、顽强的意志和周全的思考

eSNACC对ASN.1 constructors的处理

首先让我们来学习一下ASN.1的Constructors类型 。
ASN.1 constructors 类型可以将简单的预定义类型封装成复杂的数据类型。而且,这种操作可以是嵌套的,比如,constructors中还可以包含其他的constructors类型。ASN.1的constructors类型有:

SEQUENCE

SEQUENCE是一个表示有序元素集合的数据类型。集合可能为空,集合中的元素可以是任意ASN.1类型,并且元素类型可以不同。集合中的元素还可以被命名。这类似于C/C++中的结构体。

SEQUENCE OF

SEQUENCE OF 是一个表示有序元素集合的数据类型,集合可以为空。集合中的元素可以是任意ASN.1类型,但是要求所有元素为同一类型。集合中的元素可以被命名。这很类似于C/C++中的有序数组/链表。

SET

SET 是一个表示无序元素集合的数据类型,集合可以为空。集合中的元素可以是任意ASN.1类型,并且元素类型可以不同。集合中的元素可以被命名。这同样类似于C/C++中的结构体。

SET OF

SET OF 是一个表示无序元素集合的数据类型,集合可以为空。集合中的元素可以是任意ASN.1类型,但是要求所有元素为同一类型。集合中的元素可以被命名。这很类似于C/C++中的无序数组/链表。 

一眼看上去似乎SEQUENCE 和SET是一样的。其实不同就在于SEQUENCE是有序的,而SET不是。比如,在上面的例子中,SET在编码时,字段field2就可以比field1先发送,而对SEQUENCE,我们希望field1必须在field2之前先处理。

SEQUENCE OF 和SET OF的区别也就在这。

总而言之,SEQUENCE 和SEQUENCE OF依赖顺序来避免模糊。而SET 和SET OF就依赖数据类型或者每个元素的标签来唯一区分每个元素。

OPTIONAL

 SEQUENCE 等集合中出现的关键字OPTIONAL表示集合中的那个元素不是必须的:也就是可以存在也可以省略。  例如:

这对SEQUENCE OF, SET 和SET OF都适用。

DEFAULT

在某些情况下,给指定类型的某个元素设定一个默认值在编码时是非常有用的。

CHOICE

CHOICE类型是一个定义一个或者多个类型的联合的数据类型。这个联合中的字段可以被命名。每一个CHOICE的实例,都必须指定为这个联合中的一个类型。例如: 

以上内容翻译自http://www.lkn.ei.tum.de/arbeiten/faq/man/tau42_help/ttcncase8.html

 

/*******************************************休息一下***************************************

下面我们来研究eSNACC的C代码生成和C运行时库对ASN.1 constructors的处理办法:

一、因为ASN.1允许不命名集合中的字段,但是C语言要求变量必须有名字,所以eSNACC对SETs, SEQUENCEs, CHOICEs中的空字段都会自动命名。名字依赖于该字段的类型名。

二、对SEQUENCE (of)SET (of)中用OPTIONAL指定的可选元素,大部分都以指针实现。当指针不为NULL时那么就代表这个元素存在。不过当元素是OCTET STRINGs, BIT STRINGs OBJECT IDENTIFIERs类型时例外,因为这些类型很小,而且底层实现还包含一个内部的指针,利用那个指针就可以表明元素是否存在。具体请参加本系列前面的文章:对比特串、字节串、OBJECT IDENTIFIERs的编码和解码等。

三、总结:eSNACC对ASN.1 constructors->C类型转换规则:

SEQUENCE —> C struct
SET —> C struct

SEQUENCE OF —> 双向链表AsnList
SET OF —> 双向链表AsnList

ENUMERATED  —> C enum
CHOICE : 比较有意思,我们以后再专门讨论。

ASN.1到C struct和enum就是直接的对应关系,很简单。这里我们主要看看eSNACC的双向链表AsnList。

看一下AsnList的定义:

typedef struct AsnListNode
{
    
struct AsnListNode    *prev;
    
struct AsnListNode    *next;
    
void        *data;        /* this must be the last field of this structure  */
}
 AsnListNode;

typedef 
struct AsnList
{
    AsnListNode        
*first;
    AsnListNode        
*last;
    AsnListNode        
*curr;
    
int            count;        /* number of elements in list               */
    
int            dataSize;    /* space required in each node for the data */
}
 AsnList;

要注意AsnList与我们一般写的链表可能不同的是:他专门设计了一个头AsnList,而真正存放节点内容的是AsnListNode。AsnList中包含了头结点、尾节点、当前节点指针,节点元素的数目和每一个节点元素的数据大小(也就是为data分配内存时的值)。

利用AsnList,我们就能很方便的得知包括链表头尾指针、总数等的信息了。也能很方便的对整个链表进行遍历访问等操作了。

要说明的是:first节点的prev指针和last的next指针总是NULL。而且AsnList的dataSize字段必须在生成链表或者使用前初始化时就必须赋予明确的值,因为只是每创建一个AsnListNode时对data分配的内存大小数。

对AsnList的分析,我准备就只讲这些了。之所以不展开函数实现,是因为里面就是数据结构中的链表操作算法,想必大家都相当熟悉,所以不怕老生常谈,也担心班门弄斧,就算了吧。

 

不过,你可能发现有些问题:

1、上文中提到过:SEQUENCE OF是有序的,而SET OF无序的。那我们在编译成C语言时要怎么对应呢?我们看看eSNACC:他丝毫没有提这个,压根就无视这个性质!这有问题吗?

从ASN.1语义上来说,确实是没有体现,但是其实是没有问题的。因为ASN.1中所要求的有序无序,是说明数据编码和传输的问题:有序就是要保证数据定义的顺序。而我们转为C语言,本来就是按数据定义的顺序而转的,而编码解码自然就只能是C定义的顺序了,也就是说最后无论是对SEQUENCE OF还是SET OF,我们都保证了他是有序的,这当然没有问题了。

2、AsnList中存放数据的都是void*类型,这就不知道数据的原始类型了呀?

是的,AsnList中确实只是存放了void*,这导致类型丢失了。也就是你如果不小心存了不同类型的数据,他也一言不发的纵容了你。这是类型不安全的。BTW,在eSNACC的C++库中,就不存在这个问题了,这个留待以后对eSNACC的C++运行时库剖析时再说。

 

好了,本篇就到此了。

 

posted on 2012-04-25 15:01 Tim 阅读(1668) 评论(2)  编辑 收藏 引用 所属分类: eSNACC学习

评论

# re: eSNACC对ASN.1 constructors的处理[未登录] 2012-04-27 09:36 Tina

不错的文章。。。  回复  更多评论   


只有注册用户登录后才能发表评论。
网站导航: 博客园   IT新闻   BlogJava   博问   Chat2DB   管理


<2010年2月>
31123456
78910111213
14151617181920
21222324252627
28123456
78910111213

导航

统计

公告

本博客原创文章,欢迎转载和交流。不过请注明以下信息:
作者:TimWu
邮箱:timfly@yeah.net
来源:www.cppblog.com/Tim
感谢您对我的支持!

留言簿(9)

随笔分类(173)

IT

Life

搜索

积分与排名

最新随笔

最新评论

阅读排行榜