我正在做一些串行协议,并希望在python中实现基本的字节填充算法。我正努力确定最狡猾的方式。
字节填充基本上只是替换任何"保留"具有由转义字节组成的对的字节和以可逆方式转换的原始字节(例如xor' ed)。
到目前为止,我已经采用了5种不同的方法,每种方法都有一些我不喜欢的方法:
def stuff1(bits):
for byte in bits:
if byte in _EscapeCodes:
yield PacketCode.Escape
yield byte ^ 0xFF
else:
yield byte
这可能是我最喜欢的,但也许只是因为我对基于产量的发电机着迷。我担心发电机会让它变慢,但它实际上是第二快的发电机。
def stuff2(bits):
result = bytes()
for byte in bits:
if byte in _EscapeCodes:
result += bytes([PacketCode.Escape, byte ^ 0xFF])
else:
result += bytes([byte])
return result
不得不创建单个元素数组只是为了抛弃它们,因为我不知道任何"复制一个额外元素"操作。它与最慢的人联系在一起。
def stuff3(bits):
result = bytearray()
for byte in bits:
if byte in _EscapeCodes:
result.append(PacketCode.Escape)
result.append(byte ^ 0xFF)
else:
result.append(byte)
return result
似乎比直接bytes()
方法更好。实际上比yield生成器慢,并且可以一次执行一个字节(而不是需要中间1个元素集合)。但它感到野蛮。它是包装性能的中间部分。
def stuff4(bits):
bio = BytesIO()
for byte in bits:
if byte in _EscapeCodes:
bio.write(bytes([PacketCode.Escape, byte ^ 0xFF]))
else:
bio.write(bytes([byte]))
return bio.getbuffer()
我喜欢这里基于流的方法。但令人讨厌的是,它似乎不像write1
API那样可以添加1个字节,所以我必须再次制作那些中间bytes
。如果有一个"写单字节",我就喜欢这个。它的关系最慢。
def stuff5(bits):
escapeStuffed = bytes(bits).replace(bytes([PacketCode.Escape]), bytes([PacketCode.Escape, PacketCode.Escape ^ 0xFF]))
stopStuffed = escapeStuffed.replace(bytes([PacketCode.Stop]), bytes([PacketCode.Escape, PacketCode.Stop ^ 0xFF]))
return stopStuffed.replace(bytes([PacketCode.Start]), bytes([PacketCode.Escape, PacketCode.Start ^ 0xFF]))
这是最快的。但我不喜欢代码读取和中间扫描的方式。
我还尝试使用translate()
,但是AFAICT,它只能翻译1:1序列。