📄 rfc3072.txt
字号:
x.extract (data4, maxLength4);
// extr. 2nd chunk inside struct.
break;
}
x.next (); // returns x.rc == 1 at end of structure
} // end-while
break;
case 3307:
x.extract (data5, maxLength5);
// extract last chunk into data
break;
// default: none - ignore unknown chunks !!!
} // end-switch
x.next (); // returns x.rc = 1 at end of structure
} // end-while
4. 平台独立性
现在大多数计算机平台都具有8位的字节结构,这是不同的平台之间交换数据的基础,
但是在两点上不同平台可能采取不同的方法:一是二进制数字(整数和浮点数)的表示,二
是字符数据的表示(ASCII/ANSI还是EBCDIC)。前者造成字节换位的问题,比方说某个短
整数259=0x0103=X'0103'在地址4402上是如何存储的呢?有两种可能的方法:
4402 4403
01 03 先高后低还是
03 01 先低后高。
后者则用一个表来表示,表中把256个值分配给打印字符和控制字符。(在ASCII中,
字母“A”的值是0x41=65,而在EBCDIC中则是0xC1=193。)解决这些问题的方法是对数
据标准化。我们规定:二进制数值的内部表示采用高位在前的双补码表示,字符的内部表示
采用ISO 8859-1(也称为拉丁-1)。这其中的第二条还有待于推敲,因为在某些环境中,8859-1
似乎并不是最好的选择,比如在希腊和俄国也许8859-5和8859-7更合适一些。无论如何,
在特定的应用环境中如果不同的应用程序之间需要按照某种协议交换信息(不论是通过网络
还是磁盘或者别的什么),就必须规定唯一的内部字符表。因此应该给出定义变换表(和逆
转换表)的可能性。重要的是,构造的SDXF块虽然没有限定应用的地域,但是必须把数
据转化到一种标准化的格式(或网络格式)。这中间的变换不是由程序员完成的,而是由create
和extract函数完成的。管理员必须小心定义适当的转换表。
5. 压缩
在前面提到有一个标志位用于表明后续数据(原子或结构)是压缩的。这些数据在解压
缩之前不进行其它的处理,压缩由SDXF函数自动完成,对用户是透明的。“create”完成原
子块的压缩,“leave”处理结构块的压缩,“extract”对原子块解压缩,“enter”则对结构块
解压缩。透明意味着程序要只要告诉SDXF函数希望对后续数据块进行压缩就足够了。
如果要控制压缩的方法或者解压缩部分的(原始)长度,可以使用下面的附加定义:在
压缩块的头部后面加上一个压缩头,结构如下:
+-----------------------+---------------+---------------->
| chunk header | compr. header | compressed data
+---+---+---+---+---+---+---+---+---+---+---------------->
|chunkID|flg| length |md | orglength |
+---+---+---+---+---+---+---+---+---+---+---------------->
- “orglength”是原始数据(解压后)的长度;
- “md”是压缩的方法,这里介绍两种方法:
方法01:采用简单但效率不高的“游程1”或“字节游程1”算法,即连续多个相同的
字符使用字符个数和该字符来代替。具体地讲,压缩数据有一些长度不同的小节组成,每个
小节的都开始于一个“计数”字节,这是一个8位的小整数,包含长度信息。假设这个字节
的值是n,如果n是一个大于等于0小于128的整数,则后面的n+1个字节不变,如果n小
于0大于-128,后面的字节则重复-n+1次,如果n=-128则忽略。后面填充的空格一般被截
掉,但如果需要保留,可以在解压缩时把参数中的“filler”字段(参见8.2.1节)设为空格。
方法02:表示“deflate”压缩方法,来自zip压缩算法,参见[DEFLATE]。
压缩方法的编号由IANA负责维护,参见第12章。
6. 加密
在前面提到有一个标志位用于表明后续数据(原子或结构)是加密的。这些数据在解密
之前不进行其它的处理,解密由SDXF函数自动完成,对用户是透明的。“create”完成原子
块的加密,“leave”处理结构块的加密,“extract”对原子块解密,“enter”则对结构块解密。
对于特定范围的应用可以采取的加密方法有多种。某些加密方法采用成块加密算法,这意味
着加密数据的长度必须是加密块长度的倍数,在mode =3时块大小(0表示非成块加密)由
加密接口例程提供(参见第8.5节中可选字段encryptProc)。如果采用成块加密,至少要增
加一个字节,长度数据的最后一个字节表示增加的字节数减一。解密接口例程可以据此计算
实际数据的长度。
如果程序(或者网络连接握手协议)需要协商加密的方法,应该使用IANA所负责维护
的方法编号。尽管加解密对用户是透明的,但是必须把密码交给SDXF函数。加密在数据
转换成内部格式之后进行,解密则在内部格式上进行。
如果要同时对一个数据块进行压缩和加密,先进行压缩,因为经过良好加密的数据压缩
率很低。
7. 数组
数组是由块ID、长度和数据类型都相同的块组成的序列。第一点提示:从原理上来讲
没有必要为SDXF单独定义数组。并没有限制在同一个结构块中不能包含多个ID相同的块。
因此,只要反复调用SDX_next/SDX_extract就可以建立目标数组。如果反复出现ID相同的
(相对而言长度较短的)块,块包的开销可能变得很大。于是引入了数组标志位,数组块只
有一个整个原子块序列共用的头部,在数组块的头部之后跟着一个数组头。
数组头是一个短整数,包含数组元素的个数(CT),每个元素的长度都是固定的(EL),
所以整个块的长度就是CL=EL*CT+2。数据元素直接跟在数组头后面。整个数组可以通过
SDX_create来构造,使用SDX_extract读取各个元素。SDFX函数“extract”和“create”需
要使用“dataLength”和“count”参数字段。前者是数组元素的共同长度,后者是“create”
(输入)数组的实际维数。对于“extract”函数“count”同时作为输入和输出参数,在输入
时表示允许的最大维数,输出时则表示数组的实际维数。如果输出值大于输入值,则会提示
“数据剪切”的警告信息,数组填满后剩余的数据被截掉。
8. SDXF函数描述
8.1 简介
按照面向对象编程的原理,在描述数据本身的同时,还要描述操作数据的函数——“方
法”。对于程序员而言,了解方法比了解数据结构更重要,方法必须明确数据的详细规范并
保证所创建数据的一致性。SDXF对象是一个参数结构的实例,它编程的接口。具体来讲,
它指向具体的SDXF数据块,在处理该数据块时,有一个指针指向下一步要操作的真正的
内部块。使用严格的接口描述,像标准C++库一样,有利于保证平台独立性。
8.2 基本定义
8.2.1 SDXF参数结构
所有的SDXF访问函数都只需要一个参数——指向SDXF参数结构的一个指针。首先
需要定义三个基本结构:
typedef short int ChunkID;
typedef unsigned char Byte;
typedef struct Chunk
{
ChunkID chunkID;
Byte flags;
char length [3];
Byte data;
} Chunk;
然后定义参数结构:
typedef struct
{
ChunkID chunkID; // name (ID) of Chunk
Byte *container; // pointer to the whole Chunk
long bufferSize; // size of container
Chunk *currChunk; // pointer to actual Chunk
long dataLength; // length of data in Chunk
long maxLength; // max. length of Chunk for SDX_extract
long remainingSize; // rem. size in cont. after SDX_create
long value; // for data type numeric
double fvalue; // for data type float
char *function; // name of the executed SDXF function
Byte *data; // pointer to Data
Byte *cryptkey; // pointer to Crypt Key
short count; // (max.) number of elements in an array
short dataType; // Chunk data type / init open type
short ec; // extended return-code
short rc; // return-code
short level; // level of hierarchy
char filler; // filler char for SDX_extract
Byte encrypt; // Indication if data to encrypt (0 / 1)
Byte compression; // compression method
// (00=none, 01=RL1, 02=zip/deflate)
} SDX_obj, *SDX_handle;
参数结构中只有这里定义的“公开”字段能够被SDFX函数访问,具体的实现可以在
本结构中增加“私有”字段。
8.2.2 基本函数
所有的函数都是用SDX_handle作为唯一的形式参数,返回ec和rc说明函数是否成功
执行。关于ec、rc和dataType的取值详见第8.4节。
1、SDX_init:初始化参数结构。
输入:container、dataType、bufferSize (仅用于dataType = SDX_NEW only)。
输出:currChunk、dataLength (仅用于dataType = SDX_OLD )、ec、rc,同时初始
化其它字段。
2、SDX_enter:输入一个结构块,可以访问结构块内的第一个内部块。
输入:无。
输出:currChunk、chunkID、dataLength、level、dataType、ec、rc。
3. SDX_leave:离开实际操作的结构块。
输入:无。
输出:currChunk、chunkID、dataLength、level、dataType、ec、rc。
4. SDX_next : 移动到结构块内部的下一个块。
输入:无。
输出:currChunk、chunkID、dataLength、dataType、count、ec、rc。
到达结构块的尾部时,SDX_next返回rc = SDX_RC_failed和ec = SDX_EC_eoc (块尾),
并自动调用SDX_leave。
5. SDX_extract:提取块中的数据(如果是结构块,仅仅复制一份,否则转化成主机识
别格式,输入和输出依赖于具体的数据类型:
如果dataType是结构、二进制或字符,则:
输入:data、maxLength、count、filler
输出:dataLength、count、ec、rc
如果数据类型是数字(主要是浮点数),则:
输入:无。
输出:值、rc、ec。
6. SDX_select:移动到ID指定的(下一个)块。
输入:chunkID。
输出:currChunk、dataLength、dataType、ec、rc。
7. SDX_create:(在处理的结构块的尾部)创建新块。
输入:chunkID、dataLength、data、(f)value、dataType、compression、encrypt、count。
更新:remainingSize、level。
输出:currChunk、dataLength、ec、rc。
8. SDX_append:在处理的结构块的尾部增加一个完整的块。
输入:data、maxLength、currChunk
更新:remainingSize、level
输出:chunkID、chunkLength、maxLength、dataType、ec、rc
8.3 C++定义
下面是SDXF类用C++语言描述的定义(注意,此处类型“Byte”表示无符号字符,用
于位串,与用于字符串的有符号字符不同)。
class C_SDXF
{
public:
// constructors and destructor:
C_SDXF (); // dummy
C_SDXF (Byte *cont); // old container
C_SDXF (Byte *cont, long size); // new container
C_SDXF (long size); // new container
~C_SDXF ();
// methods:
void init (void); // old container
void init (Byte *cont); // old container
void init (Byte *cont, long size); // new container
void init (long size); // new container
void enter (void);
void leave (void);
void next (void);
long extract (Byte *data, long length); // chars, bits
long extract (void); // numeric data
void create (ChunkID); // structured
void create (ChunkID, long value); // numeric
void create (ChunkID, double fvalue); // float
void create (ChunkID, Byte *data, long length);// binary
void create (ChunkID, char *data); // chars
void set_compression (Byte compression_method);
void set_encryption (Byte *encryption_key);
// interface:
ChunkID id; // see 8.4.1
short dataType; // see 8.4.2
long length; // length of data or chunk
long value;
double fvalue;
short rc; // the raw return code see 8.4.3
short ec; // the extended return code see 8.4.4
protected:
// implementation dependent ...
};
8.4 公共定义:
8.4.1 ChunkID的定义:
typedef short ChunkID;
8.4.2 dataType的取值:
SDX_DT_inconsistent = 0
SDX_DT_structured = 1
SDX_DT_binary = 2
SDX_DT_numeric = 3
SDX_DT_char = 4
SDX_DT_float = 5
SDX_DT_UTF8 = 6
用于SDX_init的数据类型:
SDX_OLD = 1
SDX_NEW = 2
8.4.3 rc的取值:
SDX_RC_ok = 0
SDX_RC_failed = 1
SDX_RC_warning = 1
SDX_RC_illegalOperation = 2
SDX_RC_dataError = 3
SDX_RC_parameterError = 4
SDX_RC_programError = 5
SDX_RC_noMemory = 6
8.4.4 ec的取值:
SDX_EC_ok = 0
SDX_EC_eoc = 1 // end of chunk
SDX_EC_notFound = 2
SDX_EC_dataCutted = 3
SDX_EC_overflow = 4
SDX_EC_wrongInitType = 5
SDX_EC_comprerr = 6 // compression error
SDX_EC_forbidden = 7
SDX_EC_unknown = 8
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -