dyayaml

!!注意!!

dyayaml開発当初はろくなYAMLライブラリが無かったのは確かです。
今はlibyamlという優れたライブラリがありますので、そちらの使用を強く推奨します。
奇遇にもlibyamlはYAMLをストリームとして扱うメインの構造がdyayamlとまるで同じで、移行はとても簡単です。
無いとは思いますが既にdyayamlで作ったデータがあり、dyayamlの勝手な仕様のせいで互換性のないYAMLを抱えてしまっている方は、変換用にdyayaml2libyaml.cを用意しましたので、どうぞお使いください。
くれぐれも、dyayamlからは早々にお離れください。

なんなのなんなの

様々な言語から使えるYAMLのReader&Writerです。
たぶんC, Delphi及びBorland互換Pascal, D言語, Ada、もしかしてHaskellから使えます。

dyayamlはYAMLを破壊する

対応してない構文が多数あります。 

値(Scalar), Sequence, Mappingに対応しています
×タイプ(!)は冒頭(---)にのみつけることができます
×コメントは冒頭を除き行頭からのみ開始できます
×Unordered Set(?)には対応していません
×Mapping between sequences(? A : B)が使えません
Ordered mappings(- A : B)は使えます
×Sequence([]), Mapping({})の一行記法が使えません
値のliteral style(|)に見かけ上対応しています
×値のfolded style(>)には対応していません
×Anchor, Aliasその他雑多な機能には対応していません

…つまり、Scalar, Sequence, Mappingだけで、木構造を構成することのみできます。
あと細かいところで勝手な仕様を混ぜてますので下手にdyayamlを使うと他のYAMLライブラリで読めなくなるかもしれません。例えばタブをインデントに使うこともできます。
strictなYAMLなんてどうでもよくてそれっぽい構文が使えればそれでいい人向け。

機能面

ライブラリとしての機能は、以下のようなものがあります。 

download

latest version 

Delphiからの使い方

いい加減な説明をします。
まず、Delphiからの場合必要なのはdyayaml_omf.objとdyayaml.pasだけです。あとはポイしてください。makefileも要りません。
dyayaml.pasのimplementationのすぐ後にdyayaml_omf.objをリンクする指令があるのでそこのパスを実際にファイルを置いた位置に書き換えるだけでOKのはずです。
出力はこんな感じです。

{$APPTYPE CONSOLE}
uses
	dyayaml;

type 
	T = record
		X, Y: Integer;
	end;

var 
	Writer: TYamlWriter;
	Serializer: IYamlSerializer;
	X: T;

procedure T_Mapping(Context: Pointer); cdecl;
begin
	IO(Serializer, 'x', X.X);
	IO(Serializer, 'y', X.Y);
end;

begin
	Writer := TYamlWriter.Create('TypeIsT');
	Serializer := Writer;
	IO(Serializer, T_Mapping, nil);
	WriteLn(Writer.Output);
end.

上記コードは次の出力を行います。

--- !TypeIsT

x: 0
y: 0

上記コードのままではグローバル変数を介するか、Contextというポインタ型の引数を介するかしないとコールバック関数のT_Mappingに変数を渡せません。ところが、上記コードは何故かこう書き換えることができます。理由は説明しません。

{$APPTYPE CONSOLE}
uses
	dyayaml;

function GetContext: Pointer; register;
asm
	mov eax, ebp
end;

type 
	T = record
		X, Y: Integer;
	end;

procedure IO(Serializer: IYamlSerializer; var X: T); overload;
	procedure T_Mapping; cdecl;
	begin
		IO(Serializer, 'x', X.X);
		IO(Serializer, 'y', X.Y);
	end;
begin
	IO(Serializer, CYamlIOMapping(@T_Mapping), GetContext);
end;

var
	Writer: TYamlWriter;
	Serializer: IYamlSerializer;
	X: T;
begin
	Writer := TYamlWriter.Create('TypeIsT');
	Serializer := Writer;
	IO(Serializer, X);
	WriteLn(Writer.Output);
end.

そして、このprocedure IO(Serializer: IYamlSerializer; var X: T); overload;という関数は、そのまま読み込みにも使うことができます。
いい加減な説明終わり。

リンク