相互に依存関係がある解析対象のバイナリ ファイルのペアがあります。Preonライブラリを使用しています。
ファイルの名前は rec.table および rec.offset です。一方は他方へのオフセット インデックスです (rec.offset ファイルの 32 ビット整数の行で、rec.table へのバイト オフセットを表します)。rec.offset の行数は、rec.table で使用可能なデータの 1 つ (recordCount フィールド) によって異なります。以下の @BoundList の状況に見られるように、オフセット エントリ リストのサイズを提供する必要があり、そのリストを使用してレコード エントリにアクセスする必要があります。
私は次の設定をしています:
package bytecodeparsing;
import org.codehaus.preon.annotation.BoundList;
import org.codehaus.preon.annotation.BoundNumber;
public class RecTable {
// Using this instead of 'outer' due to circular dependencies
@SuppressWarnings("unused") // Actually used in Preon expression below
private RecOffsets recOffsets;
@BoundNumber int version;
@BoundList(size="4") byte[] pad; // 4 byte pad to ignore.
@BoundNumber long recordCount;
// offset is in RecOffsets, which must then be an outer class of this, but that class needs to know how many entries there
// are, which is the recordCount value here. Circular dependencies?
@BoundList(offset="recOffsets.offsets[index]", size="recordCount") Rec[] recs;
public void setDependencies(RecOffsets recOffsets) {
this.recOffsets = recOffsets;
}
}
と:
package bytecodeparsing;
import org.codehaus.preon.annotation.BoundList;
import org.codehaus.preon.annotation.BoundNumber;
public class RecOffsets {
@SuppressWarnings("unused") // Actually used in Preon expression below
private RecTable recTable; // maybe use this instead of 'outer' due to circular dependencies?
@BoundList(size="RecTable.recordCount+1") long[] offsets;
public void setDependencies(RecTable recTable) {
this.recTable = recTable;
}
}
これを実行すると、記事「Preon での可変レコード長の解析」で報告されているようなエラーが表示されます。
org.codehaus.preon.CodecConstructionException: Failed to construct codec.
at org.codehaus.preon.codec.ArrayCodecFactory.getSizeExpression(ArrayCodecFactory.java:152)
at org.codehaus.preon.codec.ArrayCodecFactory.create(ArrayCodecFactory.java:93)
at org.codehaus.preon.codec.CompoundCodecFactory.create(CompoundCodecFactory.java:59)
at org.codehaus.preon.DefaultCodecFactory$DecoratingCodecFactory.create(DefaultCodecFactory.java:266)
at org.codehaus.preon.codec.ObjectCodecFactory.harvestBindings(ObjectCodecFactory.java:184)
at org.codehaus.preon.codec.ObjectCodecFactory.createCodec(ObjectCodecFactory.java:129)
at org.codehaus.preon.codec.ObjectCodecFactory.create(ObjectCodecFactory.java:112)
at org.codehaus.preon.codec.CachingCodecFactory.create(CachingCodecFactory.java:130)
at org.codehaus.preon.codec.CompoundCodecFactory.create(CompoundCodecFactory.java:59)
at org.codehaus.preon.DefaultCodecFactory$DecoratingCodecFactory.create(DefaultCodecFactory.java:266)
at org.codehaus.preon.DefaultCodecFactory.create(DefaultCodecFactory.java:137)
at org.codehaus.preon.DefaultCodecFactory.create(DefaultCodecFactory.java:65)
at org.codehaus.preon.DefaultCodecFactory.create(DefaultCodecFactory.java:60)
at org.codehaus.preon.Codecs.create(Codecs.java:279)
at bytecodeparsing.PreonParsing.create(PreonParsing.java:76)
at bytecodeparsing.PreonParsing.<init>(PreonParsing.java:51)
Caused by: org.codehaus.preon.el.BindingException: Failed to create binding for bound data called recTable
at org.codehaus.preon.codec.BindingsContext.selectAttribute(BindingsContext.java:101)
at org.codehaus.preon.el.ImplicitsContext.selectAttribute(ImplicitsContext.java:52)
at org.codehaus.preon.el.LimboWalker.vexpr(LimboWalker.java:667)
at org.codehaus.preon.el.LimboWalker.vexpr(LimboWalker.java:488)
at org.codehaus.preon.el.Expressions.arithmetic(Expressions.java:125)
at org.codehaus.preon.el.Expressions.createInteger(Expressions.java:102)
at org.codehaus.preon.codec.ArrayCodecFactory.getSizeExpression(ArrayCodecFactory.java:148)
... 19 more
このエラーは、オフセット配列のサイズ属性で recTable が使用されていることを示しています。他の質問と同様に、一定のサイズを指定するか、単純な @BoundNumber バインディングを偽造してそれを参照することで、このエラーを回避できます。
上記でリンクした他の質問では、循環依存関係が 2 つのクラスにまたがっている状況がありますが、1 つのファイルを解析しているときに、2 つの別々のファイルを解析する必要があります。Wilfred Springer が言及したパッチ (PREON-9) は、既に github リポジトリ (PREON-48) に統合されていると思います。
この循環依存に対処するにはどうすればよいですか? 私はトリックを逃していますか?