JUCE valuesの検証 (valuetree)

#概要

juce_data_structuresに属するValuetreeについです。
ラッパークラスとしてCachedValue<Type>がありますがまずは基底のvaluetreeから見ていきます。

公式のドキュメントによると...

> 自由形式のデータを保持するために使用でき、独自の元に戻すやり直しの動作を処理できる強力なツリー構造。

つまり構造体のようなデータ構造が定義でき、データにたいしてUndo/Redoが可能であると読み取れるが果たして。
実用できると大変便利なクラスですね。


#詳細

自由形式のデータを保持するために使用でき、独自の元に戻すやり直しの動作を処理できる強力なツリー構造。

ValueTreeには、名前付きプロパティのリストがvarオブジェクトとして格納されており、任意の数のサブツリーも格納されています。

ValueTreeオブジェクトはスタック上に作成し、共有データコンテナへの軽量な参照であるため、コピーするのを恐れません。
別のValueTreeのコピーを作成すると、createCopy（）を明示的に呼び出す必要があるツリーの別の深いコピーを作成するために、同じ基礎オブジェクトへの新しい参照が作成されます。

各ValueTreeには型名があり、XmlElementにはタグ名があり、ValueTreeの構造の多くはXmlElementツリーに似ています。 
ValueTreeをXmlElementとの間で変換することができます。
**XMLにテキスト要素が含まれていない限り、変換はうまく動作し、適切なシリアル化形式を作成します。**
**非常に高速でコンパクトなバイナリ形式にシリアル化することもできます。**

データを変更するすべてのメソッドは、オプションのUndoManagerを使用します.UndoManagerは、オブジェクトの変更を追跡するために使用されます。
これが機能するには、ツリー内の任意のノードに対するすべての操作に対して、常に同じUndoManagerを常に使用するように注意する必要があります。

ValueTreeは一度に1つの親の子にしかなりません。
そのため、あるツリーから別のツリーに移動する場合は、追加する前に必ず削除してください。
これはあなたの元に戻す/やり直しの鎖を台無しにするかもしれないので、注意してください！]
あなたが何か危険なことをしようとすると、デバッグビルドでアサーションを打つべきですが、まだ間違っている可能性があります。

ツリー内の子ノードは固定順序を持っていますが、プロパティは特定の順序で格納されることは保証されていないので、プロパティのインデックスがプロパティが追加された順序に対応することを期待しないでください他のプロパティが追加または削除されると、一定のままになります。

プロパティーが変更されたときやノードが追加または削除されたときに通知されるリスナーをValueTreeに追加できます。

#雑感
クラスリファレンスは以下

[クラスリファレンス Valuetree](https://juce.com/doc/classValueTree)

ざっとメソッドを見るによくあるXMLライブラリに似たメソッドになっているようだ。
ValueTreeクラスを最小のデータコンテナとして親子関係の構築とValueTree自体にプロパティーを与えることができる。
与えたプロパティーは名前と値を持つようだ。

ソース上でのデータ構造の定義とXMLデータの読み込みを検証することにする。



#検証コード

[github]()


##　プロパティの与え方など

```
	//undo manager作成
	juce::UndoManager undomanager(200000, 30);

	//値の初期化
	juce::ValueTree v(juce::Identifier("vertices"));
	juce::Value count(var(1));

	undomanager.beginNewTransaction();
	v.setProperty("count", count, &undomanager);
	v.setProperty("x", 10, &undomanager);
	v.setProperty("y", 5, &undomanager);
	v.setProperty("z", -15, &undomanager);

	//count = 1
	juce::Logger::outputDebugString(v["count"].toString());

	//cout <- 12
	undomanager.beginNewTransaction();
	v.setProperty("count", 12, &undomanager);
	//count = 12
	juce::Logger::outputDebugString( v["count"].toString() );

	//変数 count の値を見ると変わっていない参照は無い
	juce::Logger::outputDebugString(count.toString());

	//undoをしてみる count = 1になる
	undomanager.undo();
	juce::Logger::outputDebugString( "undo = " + v["count"].toString());


	//プロパティ数を調べる
	juce::Logger::outputDebugString(juce::String(v.getNumProperties()));
 
```

```
JUCE v5.2.0
1
12
1
undo = 1
4
```

## XMLへの出力

read/writeがうまくいっていないので調査する
DTDが指定できるようだが・・・。


```
	//********************************************** 
	//	XMLでの運用 
	//********************************************** 

	//	XML(文字列）へ出力(デバッグ用途）	
	juce::Logger::outputDebugString(v.toXmlString());


	//実際に読み書き前提で使用する場合
	juce::XmlElement* outxml = v.createXml();
	//e->writeToFile();

	//カレントのワーキングディレクトリを取得
	juce::File f = juce::File::getCurrentWorkingDirectory();
	juce::String filepath = f.getFullPathName() + "\\test.xml";

	//XMLファイルの書き出し
	outxml->writeToFile( filepath ,"" );
	
	delete outxml;

	//XMLの読み込み 
	juce::File readf(filepath);
	juce::XmlDocument xmldoc(readf);
	juce::ValueTree v2(juce::Identifier("vertices"));
	juce::XmlElement* inxml = xmldoc.getDocumentElement();
	v2.fromXml(*inxml);

	juce::Logger::outputDebugString(juce::String(v2.getNumChildren()));
	juce::Logger::outputDebugString(juce::String(v2.getNumProperties()));
	juce::Logger::outputDebugString(v2.toXmlString());
	delete inxml;

```

##バイナリフォーマット

```
	//********************************************** 
	//	Juceバイナリフォーマットでの運用 
	//********************************************** 

	//バイナリフォーマットでの出力
	filepath = f.getFullPathName() + "\\test.bin";
	juce::FileOutputStream binfile( filepath );
	v.writeToStream(binfile);
```