概要
PHPなどの連想配列的になんでも代入できるクラスが使ってみたくてライブラリを作成してみました。Arduino向けなので動的メモリ確保ではなく、最初に必要量だけメモリ確保する作りになっています。
作成物
上記のリポジトリになります。ライブラリマネージャには登録済みなのでAssocTreeで検索すればでるはずです。
#include <AssocTree.h>
AssocTree<2048> doc;
void setup() {
Serial.begin(115200);
doc["user"]["name"] = "Taro";
doc["user"]["age"] = 20;
doc["flags"]["debug"] = true;
doc["values"][0] = 1;
doc["values"][1] = 2;
doc["values"][2] = 3;
const int age = doc["user"]["age"].as<int>(0);
const bool debug = doc["flags"]["debug"];
Serial.print("age=");
Serial.print(age);
Serial.print(" debug=");
Serial.println(debug ? "true" : "false");
String json;
if (doc.toJson(json)) {
Serial.println(json);
}
}
void loop() {}
こんな漢字の使い方ができます。何に使うとよいのかはまあよくわからないのですが、作ってみたかったので作成しています。
AssocTree<2048> doc;
上記でテンプレートを利用して、2048バイトのメモリ確保をしています。
union Value {
bool asBool;
int32_t asInt;
double asDouble;
StringSlot asString;
constexpr Value() : asInt(0) {}
} value;
データ自体は上記のようなunionに保存されています。文字列以外は直接データを保存してあり、文字列はStringSlotという別管理になっています。データの保持形式自体はよくある形で親や子供などへのリンクを持っていて、ツリーを保持しています。
Codexを利用して作成したのですが、どうもリストと文字列を別管理したがっていました。そしてメモリ量指定でどんな割合でも使えるようにしたかったのですが、リストに7割みたいな事前確保をして、想定と違う使い方だと最後まで使えない感じの設計をしてきます。
今回は2048バイトなどと事前確保したメモリの先頭からリストで利用、後ろから文字列で利用をして使う形にしてもらいました。両方向から事前確保のメモリを使ってもらうので、どっちをたくさん使ってもメモリが無駄になりません。
他のライブラリをみたのですが、完全動的確保でどんどんメモリを使っていくタイプが多かったです。その場合にはメモリが細切れになったりしてちょっと気になりますよね。
doc.gc();
このライブラリでもデータの削除を行うと抜けがでるので、gc関数を準備しました。これを実行すると参照されていない文字列を詰める動きで空き容量を広げる動きになります。
まとめ
あまり有効なユースケースが見つからないのですが、雑に設計しているときの一時データ保存領域にはいいのかなと思います。設計が固まったところで構造体などに変更したほうが効率的ですが、ちょっとしたことには連想配列的な動きって便利ですよね?



コメント