Rubyでフォーマットのあるバイナリを読み込む場合、String#unpackを使うのがよくあるパターン。とはいえ使いづらい点もあって
- フォーマット文字列が長さ情報を持っているのに、何バイト読んだかの情報が取れない
- unpack自体はデータを消費しないので、次のデータを読もうとすると自分で進めないといけない
これで、例えばデータ自体の内容によってフォーマットが切り替わるようなデータを処理しようとすると、フォーマットから長さを計算して固定長切り出してフォーマットに従ってunpackして……という鉄板コードが並ぶことに。
やってられないので、こんなのを考えてみた。
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
class String | |
def unpack!(fmt) | |
ret = unpack(fmt) | |
slice!(0,ret.pack(fmt).size) | |
ret | |
end | |
end | |
# Use like this. | |
str = "\0\xaa\x01\x55\xff" | |
until str.empty? | |
case str.unpack!('C').first | |
when 0 | |
puts str.unpack('C') | |
when 1 | |
puts str.unpack('n') | |
end | |
end |
unpackした結果をpackし直して長さを求めるという手抜きかつ富豪な実装だけど、これだけでデータ処理コード自体の見通しはだいぶ良くなったりする。
0 件のコメント:
コメントを投稿