Qtの基礎 - TOML

提供: MochiuWiki : SUSE, EC, PCB

2024年9月18日 (水) 01:36時点におけるWiki (トーク | 投稿記録)による版 (概要)

概要

TOML (Tom's Obvious, Minimal Language) は、設定ファイルフォーマットとして設計された。
QtでTOMLを使用することは、アプリケーションの設定や構成を管理する上で有効である。

TOMLの特徴として、人間が読み書きしやすい形式であることが挙げられる。
キーと値のペアを基本構造とし、階層的なデータ構造も表現することができる。

日付や時刻、真偽値、数値等、様々なデータ型をサポートしている。

Qtには組み込みのTOMLパーサーが存在しないため、サードパーティ製ライブラリを使用する必要がある。
一般的に、toml11ライブラリtoml++ライブラリ等のサードパーティ製ライブラリがよく使用されている。
これらのライブラリを使用することにより、TOMLファイルの読み込み、書き込み、データの解析が容易になる。

TOMLの構文は、基本的な形式は<キー> = <値>のペアで記述する。
セクションを使用してデータをグループ化することもでき、これはブラケット[]で囲むことで表現する。

TOMLを使用するメリットとして、設定の管理が容易になることが挙げられる。
例えば、アプリケーションの起動時にTOMLファイルから設定を読み込み、実行時に変更された設定をTOMLファイルに書き込むような使用方法が考えられる。

TOMLは他の設定ファイル形式 (JSONやYAML等) と比較して、より直感的で読みやすい構文を持っている。
特に複雑な階層構造を持つ設定データを扱う場合に、そのメリットが発揮される。

ただし、TOMLを使用する場合は、選択したライブラリの依存関係管理やパフォーマンスへの影響を考慮する必要がある。


TOMLの構文

TOMLファイルの主な構文要素を以下に示す。

  • キーと値のペア
    基本的な形式は、<キー名> = <値> である。
    例: name = "TOML Example"

  • 文字列
    • 基本文字列
      ダブルクォートで囲む
      "Hello"
    • リテラル文字列
      シングルクォートで囲む
      'C:\Users\username'

  • 数値
    • 整数
      42
    • 浮動小数点
      3.14

  • ブーリアン
    true または false

  • 日付と時刻
    ISO 8601形式を使用する。
    例: date = 2023-03-27T15:32:00Z

  • 配列
    角括弧で囲む。
    例: colors = [ "red", "yellow", "green" ]

  • テーブル (セクション)
    角括弧で囲んだ名前で定義する。
    例:
       [database]
       server = "192.168.1.1"
       ports = [ 8001, 8001, 8002 ]
    

  • インラインテーブル
    中括弧で囲む。
    例: point = { x = 1, y = 2 }

  • テーブルの配列
    2重の角括弧で定義する。
    例:
       [[fruits]]
       name = "apple"
    
       [[fruits]]
       name = "banana"
    

  • コメント
    シャープ記号 (#) を使用する。



同期処理

TOMLの読み込み

以下の例では、toml++ライブラリを使用して、TOMLファイルを読み込んでいる。
toml++ライブラリを使用する場合は、プロジェクトにtoml++ライブラリをリンクする必要がある。

 #include <QFile>
 #include <QTextStream>
 #include <stdexcept>
 #include <toml++/toml.h>
 
 class TomlHandler
 {
 public:
    TomlHandler() = default;
 
    // TOMLファイルを読み込む
    toml::table readToml(const QString &filename)
    {
       try {
          return toml::parse_file(filename.toStdString());
       }
       catch (const toml::parse_error &err) {
          throw std::runtime_error(QString("TOMLファイルの解析エラー: %1").arg(err.description().c_str()).toStdString());
       }
    }
 
    // TOMLデータから特定の値を取得 (テンプレート関数)
    template<typename T>
    T getValue(const toml::table &data, const QString &key)
    {
       try {
          return data[key.toStdString()].value<T>();
       }
       catch (const toml::type_error &err) {
          throw std::runtime_error(QString("値の取得エラー: %1").arg(err.what()).toStdString());
       }
    }
 };


以下の例では、上記のクラスを使用してTOMLファイルを読み込んでいる。

 #include <QDebug>
 #include "TomlHandler.h"
 
 int main()
 {
    TomlHandler handler;
 
    try {
       // TOMLファイルを読み込む
       auto data = handler.readToml("config.toml");
 
       // 値を取得する
       QString name = handler.getValue<QString>(data, "name");
       int age = handler.getValue<int>(data, "age");
 
       qDebug() << "Name:" << name;
       qDebug() << "Age:" << age;
    }
    catch (const std::exception &e) {
       qCritical() << "エラー: " << e.what();
       return -1;
    }
 
    return 0;
 }


TOMLファイルの書き込み

以下の例では、toml++ライブラリを使用して、TOMLファイルを書き込んでいる。
toml++ライブラリを使用する場合は、プロジェクトにtoml++ライブラリをリンクする必要がある。

 #include <QFile>
 #include <QTextStream>
 #include <stdexcept>
 #include <toml++/toml.h>
 
 class TomlHandler
 {
 public:
    TomlHandler() = default;
 
    // TOMLファイルを読み込む
    toml::table readToml(const QString &filename)
    {
       try {
          return toml::parse_file(filename.toStdString());
       }
       catch (const toml::parse_error &err) {
          throw std::runtime_error(QString("TOMLファイルの解析エラー: %1").arg(err.description().c_str()).toStdString());
       }
    }
 
    // TOMLデータをファイルに書き込む
    void writeToml(const QString &filename, const toml::table &data)
    {
       QFile file(filename);
       if (!file.open(QIODevice::WriteOnly | QIODevice::Text)) {
          throw std::runtime_error(QString("ファイルオープンエラー: %1").arg(filename).toStdString());
       }
 
       QTextStream out(&file);
       out << QString::fromStdString(toml::toml_formatter(data).format());
 
       file.close();
    }
 
    // TOMLデータから特定の値を取得 (テンプレート関数)
    template<typename T>
    T getValue(const toml::table &data, const QString &key)
    {
       try {
          return data[key.toStdString()].value<T>();
       }
       catch (const toml::type_error &err) {
          throw std::runtime_error(QString("値の取得エラー: %1").arg(err.what()).toStdString());
       }
    }
 
    // TOMLデータに値を設定する (テンプレート関数)
    template<typename T>
    void setValue(toml::table &data, const QString &key, const T &value)
    {
       data[key.toStdString()] = value;
    }
 };


以下の例では、上記のクラスを使用してTOMLファイルを書き込んでいる。

 #include <QDebug>
 #include "TomlHandler.h"
 
 int main()
 {
    TomlHandler handler;
 
    try {
       // TOMLファイルを読み込む
       auto data = handler.readToml("config.toml");
 
       // 値を取得
       QString name = handler.getValue<QString>(data, "name");
       int age = handler.getValue<int>(data, "age");
 
       qDebug() << "Name:" << name;
       qDebug() << "Age:" << age;
 
       // 値を設定
       handler.setValue(data, "location", "Tokyo");
 
       // 変更したデータを書き込む
       handler.writeToml("config_updated.toml", data);
    }
    catch (const std::exception &e) {
       qCritical() << "エラー: " << e.what();
       return -1;
    }
 
    return 0;
 }