令我惊讶的是,这还没有发布!
在一致的开销字节填充(COBS)算法用于分隔字节流。
我们选择一个帧标记(我们将使用0x00),并且在流中出现0x00的任何地方都将其替换为字节数,直到下一个出现0x00为止(我们将其称为里程碑)。这将值的范围从0..255减小到1..255,从而使0x00可以明确地界定流中的帧。
在一个里程碑,如果下一个255B不包含0x00,则超出最大里程碑长度-算法必须“停顿”在255B并放置另一个里程碑。这是“一致的开销”。
第一个字节将是第一个里程碑,最后一个里程碑将是直到帧标记的字节数。
维基百科的一些示例(最好阅读彩色文章):
0x00 as frame marker
Unencoded data (hex) Encoded with COBS (hex)
00 01 01 00
00 00 01 01 01 00
11 22 00 33 03 11 22 02 33 00
11 22 33 44 05 11 22 33 44 00
11 00 00 00 02 11 01 01 01 00
01 02 03 ... FD FE FF 01 02 03 ... FD FE 00
00 01 02 ... FC FD FE 01 FF 01 02 ... FC FD FE 00
01 02 03 ... FD FE FF FF 01 02 03 ... FD FE 02 FF 00
02 03 04 ... FE FF 00 FF 02 03 04 ... FE FF 01 01 00
03 04 05 ... FF 00 01 FE 03 04 05 ... FF 02 01 00
挑战:要在最短的程序中实现这一目标。
- 输入是未编码的字节流/数组,输出是已编码的字节流/数组
- 使用任何类型的二进制标准输入/输出
- 最终帧标记不是必需的
- 程序可以返回超大数组
- 以254个非零字节结尾的流不需要尾随的0x00
笔记
- 最坏情况下的返回长度是
numBytes + (numBytes / 254) + 1
例
我们有字节数组
[0] 0x01
[1] 0x02
[2] 0x00
[3] 0x03
[4] 0x04
[5] 0x05
[6] 0x00
[7] 0x06
对于每一个,0x00
我们都需要(里程碑)说明下一个目标0x00
。
[0] 0x03 #Milestone. Refers to the original [2] - "The next 0x00 is in 3B"
[1] 0x01 #Original [0]
[2] 0x02 #Original [1]
[3] 0x04 #Milestone. Refers to the original [6] - "The next 0x00 is in 4B"
[4] 0x03 #
[5] 0x04 #
[6] 0x05 # Originals [3..5]
[7] 0x02 #Milestone. Refers to the end frame marker
[8] 0x06 #Original [7]
[9] 0x00 #Optional. End frame marker.
3
您可能应该将其包括在规范中:作为一个特殊的例外,如果数据包以254个非零字节为一组结束,则无需添加尾随零字节。在某些情况下,这样可以节省一个字节。(引用Wikipedia)
—
阿纳尔德
@LuisMendo同意。现在,我已经遍历了所有测试用例,现在可以确定这是个不足的地方。
—
阿纳尔德
@Arnauld,我已经说过最终框架制造商是没有必要的:)
—
Patrick
在示例中,第一个输出字节应该是0x03,而不是0x02,除非我弄错了...
—
OlivierGrégoire19年
@Arnauld关于以254个非零字节结尾的特殊情况:同意,这是最后一个帧标记的另一个问题。这就是为什么第六个示例没有结尾
—
肯尼迪
01
但01
第九个示例中有两个s的原因(其中有254个非零字节,后跟一个零)。