Short quantity

16-bitデータの配列がプラットフォームを越えて正しくセーブできないという問題は、一度直したつもりになっておきながら実はまったく直っていなくて、思ったよりはややこしい、ということだけは分かっていたわけだが、もう一度見直してみたところ、前回コードを書いたときに立てていた仮説が間違っていたのは無理もないよな、ということで納得。

squeak-harvestには、かっこつけて"But the margin of this email is too small to contain it."などと書いてみたが、せっかくだから書いておこう。

digitAt:はプラットフォームのエンディアンに関わらず、同じレシーバーと引数ならいつも同じ値を返す、つまり実質的にエンディアンを吸収するので、Stream>>nextWordsPutAll:がデータを書き出すときはバイトオーダーはどうであれ、常にワード内のLSBから書き出していくことになる。何でLSBからなんだ、という疑問もありうるわけだが、LargeIntegerとの互換性を考えればそのほうが便利なわけだな。ただし、ワード内のshortワードの順番はエンディアンによって変わっているので、objectForDataStream:ではshortとして16ビットの値を入れ替えたものを返すようにすれば、ビッグエンディアンのプラットフォームでもリトルエンディアンのプラットフォームでも同じ順番で書かれるようになる。

一方、読み込むときには基本的にBitBltエンディアンを吸収してしまうのでワードないでのバイトスワッピングはしなくてよいのだが、16ビットワード内をみると、バイト順が狂ってしまっているので、0と1、2と3バイト目をそれぞれ入れ替えないと元に戻らない、という次第。

短くまとめれば、思わぬところに出てきたバイトオーダー変換の非対称性とでもいうべきだろうか。