default_ endian

バイナリ入出力に"default_"エンディアンなるものを追加しました。
endian.hppの差分
binary_io.hppの差分
これまで扱ってきた多くのフォーマットは、フォーマットあるいはデータフィールド毎にエンディアンが決まっていました。
しかし、ISO 9660では一つのデータを複数のエンディアンで記録するため、構造体のメンバ毎にエンディアンを指定する方法では対応できません。
このようなデータには入出力の際にエンディアンを選択する手段が必要です。
"default_"エンディアンはそのためのエンディアン指定です。


例を見てみましょう。

#include <hamigaki/struct_traits.hpp>
#include <boost/mpl/list.hpp>
#include <boost/cstdint.hpp>

namespace my {

struct point
{
    boost::int32_t x;
    boost::int32_t y;
};

struct both_point
{
    point lsb;
    point msb;
};

} // namespace my

namespace hamigaki {

template<>
struct struct_traits<my::point>
{
private:
    typedef my::point self;

public:
    typedef boost::mpl::list<
        hamigaki::member<self, boost::int32_t, &self::x, default_>,
        hamigaki::member<self, boost::int32_t, &self::y, default_>
    > members;
};

template<>
struct struct_traits<my::both_point>
{
private:
    typedef my::both_point self;

public:
    typedef boost::mpl::list<
        hamigaki::member<self, my::point, &self::lsb, little>,
        hamigaki::member<self, my::point, &self::msb, big>
    > members;
};

} // namespace hamigaki

#include <hamigaki/binary_io.hpp>
#include <iostream>

int main()
{
    const char raw[] =
        "\x64\x00\x00\x00\xFF\xFF\xFF\xFF" // "100, -1" for LSB
        "\x00\x00\x00\x64\xFF\xFF\xFF\xFF" // "100, -1" for MSB
    ;

    // エンディアン指定なし
    // ネイティブエンディアン(ここではリトルエンディアン)で読み込む
    my::point lsb;
    hamigaki::binary_read(raw, lsb);
    std::cout << lsb.x << ", " << lsb.y << '\n'; // 100, -1

    // ビッグエンディアンで読み込む
    my::point msb;
    hamigaki::binary_read<hamigaki::big>(raw+8, msb);
    std::cout << msb.x << ", " << msb.y << '\n'; // 100, -1

    // 構造体のメンバなら親のstruct_traitsに従う
    my::both_point data;
    hamigaki::binary_read(raw, data);
    std::cout << data.lsb.x << ", " << data.lsb.y << '\n'; // 100, -1
    std::cout << data.msb.x << ", " << data.msb.y << '\n'; // 100, -1
}

pointのメンバ変数x,yはdefault_エンディアンの設定になっています。
default_エンディアンのフィールドはbinary_read()指定したエンディアンで読み込まれます。
エンディアン指定なしバージョンのbinary_read()はnativeを指定したのと同じ意味です。


both_pointはエンディアンの異なる2つのpointをメンバ変数に持っています。
ここで指定したエンディアンは子のdefault_エンディアンのメンバ変数に伝播されます。
ですから、data.lsb.xはリトルエンディアン、data.msb.xはビッグエンディアンといった具合になります。


早速、ISO 9660のPath Table Recordに適用してみました。
path_table_record.hppの差分
読み込みの場合はネイティブのPath Tableしか見なかったので問題ありませんでしたが、書き込みの場合は二通り出力する必要があるのでdefault_エンディアンにしてあります。
これでiso_file_sinkの実装にも使えますね。