附录 C. 伪代码 (Pseudocode)
一个 CBOR 数据项的格式良好性可以用图 1 中的伪代码来检查. 数据格式良好, 当且仅当:
-
该伪代码没有 "fail";
-
伪代码执行完毕后, 输入中没有剩余字节 (流式应用除外)
该伪代码有如下前提条件:
-
take(n) 从输入数据中读取 n 个字节, 并把它们作为字节串返回. 如果已经没有 n 个字节可用, 则 take(n) 失败.
-
uint() 通过按网络字节序解释字节串, 把字节串转换为无符号整数.
-
算术运算与 C 语言中一致.
-
所有变量都是范围足够的无符号整数.
well_formed (breakable = false) {
// process initial bytes
ib = uint(take(1));
mt = ib >> 5;
val = ai = ib & 0x1f;
switch (ai) {
case 24: val = uint(take(1)); break;
case 25: val = uint(take(2)); break;
case 26: val = uint(take(4)); break;
case 27: val = uint(take(8)); break;
case 28: case 29: case 30: fail();
case 31:
return well_formed_indefinite(mt, breakable);
}
// process content
switch (mt) {
// case 0, 1, 7 do not have content; just use val
case 2: case 3: take(val); break; // bytes/UTF-8
case 4: for (i = 0; i < val; i++) well_formed(); break;
case 5: for (i = 0; i < val*2; i++) well_formed(); break;
case 6: well_formed(); break; // 1 embedded data item
}
return mt; // finite data item
}
well_formed_indefinite(mt, breakable) {
switch (mt) {
case 2: case 3:
while ((it = well_formed(true)) != -1)
if (it != mt) // need finite embedded
fail(); // of same type
break;
case 4: while (well_formed(true) != -1); break;
case 5: while (well_formed(true) != -1) well_formed(); break;
case 7:
if (breakable)
return -1; // signal break out
else fail(); // no enclosing indefinite
default: fail(); // wrong mt
}
return 0; // no break out
}
图 1: 格式良好性检查的伪代码
请注意, 一个完整的 CBOR 解码器其余的复杂度在于如何把已解析的数据以恰当的形式呈现给应用.
主类型 0 和 1 的设计使得在 C 语言中可以从一个有符号整数直接编码, 而无需对正数/负数做 if-then-else 判断 (图 2). 这利用了一个事实: 主类型 1 的变换 (-1-n) 在 C 的无符号算术中与 ~n (按位取反) 相同; 于是 ~n 在负数情形可表示为 (-1)^n, 而 0^n 在非负情形保持 n 不变. 一个数的符号可以通过把该数算术右移比其位长少一位的位数 (例如对于 64 位数右移 63 位), 转换为: 负数时为 -1, 非负数 (0 或正数) 时为 0.
void encode_sint(int64_t n) {
uint64t ui = n >> 63; // extend sign to whole length
mt = ui & 0x20; // extract major type
ui ^= n; // complement negatives
if (ui < 24)
*p++ = mt + ui;
else if (ui < 256) {
*p++ = mt + 24;
*p++ = ui;
} else
...
图 2: 编码有符号整数的伪代码