「Qtの基礎 - TOML」の版間の差分

提供:MochiuWiki - SUSE, Electronic Circuit, PCB
ナビゲーションに移動 検索に移動
161行目: 161行目:
   
   
  # CMakeコマンドを使用する場合
  # CMakeコマンドを使用する場合
  cmake -DCMAKE_BUILD_TYPE=Release \
  cmake -DCMAKE_CXX_COMPILER=<G++ 8以降のG++> \
      -DCMAKE_BUILD_TYPE=Release           \
       -DCMAKE_INSTALL_PREFIX=<toml++ライブラリのインストールディレクトリ> \
       -DCMAKE_INSTALL_PREFIX=<toml++ライブラリのインストールディレクトリ> \
       -DBUILD_EXAMPLES=ON       \  # サンプルコードもインストールする場合
       -DBUILD_EXAMPLES=ON                 \  # サンプルコードもインストールする場合
       ..
       ..
  make -j $(nproc)
  make -j $(nproc)
169行目: 170行目:
   
   
  # Meson & Ninjaを使用する場合
  # Meson & Ninjaを使用する場合
  meson setup ./build                                   \
  CXX=<G++ 8以降のG++> meson setup ./build                       \
      -Dprefix=<toml++ライブラリのインストールディレクトリ> \
                    -Dprefix=<toml++ライブラリのインストールディレクトリ> \
      -Dbuild_examples=true  # サンプルコードもインストールする場合
                    -Dbuild_examples=true  # サンプルコードもインストールする場合
  Ninja -C build -j $(nproc)
  ninja -C ./build -j $(nproc)
  Ninja -C build install
  ninja -C ./build install
<br>
<br>
==== ライブラリの指定 ====
==== ライブラリの指定 ====

2024年9月18日 (水) 02:36時点における版

概要

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++ライブラリは、C++ 17以降で記述されたヘッダファイルのみのTOMパーサーおよびシリアライザーライブラリである。
このライブラリは、TOML v1.0.0仕様に完全準拠しており、使いやすい設計が特徴である。

主な特徴として、テンプレートベースの設計が挙げられる。
これにより、コンパイル時の型チェックが可能となり、実行時のパフォーマンスが向上する。
また、例外を使用しないエラーハンドリングをサポートしており、例外が禁止されている環境でも問題なく使用できる。

toml++は、UTF-8エンコーディングを完全にサポートしており、国際化されたアプリケーションでの使用が容易になる。
さらに、コメントの保持機能も備えており、TOMLファイルを読み込んで修正した後、元のコメントを保持したまま書き出すことができる。

toml++ライブラリは、単一ヘッダファイル版と複数ヘッダファイル版の両方が提供されており、プロジェクトの要件に応じて適切なものを選択することができる。

toml++ライブラリの使用例としては、設定ファイルの読み書き、データのシリアライズ / デシリアライズ、構造化されたデータの保存等が挙げられる。
C++の標準ライブラリと密接に統合されているため、std::stringクラスやその他のSTLコンテナとの相互運用性が高い。

パフォーマンス面では、toml++ライブラリは他の多くのTOMLパーサーよりも高速であることが報告されている。
大規模なTOMLファイルを扱う場合や、頻繁なパース / シリアライズ操作が必要なアプリケーションで特に威力を発揮する。

ドキュメンテーションも充実しており、GitHubリポジトリには詳細な使用方法や設定オプションが記載されている。
また、豊富な例やチュートリアルも提供されているため、初めて使用する開発者でも迅速に習得することができる。

toml++ライブラリのライセンス

toml++ライブラリのライセンスはMITライセンスに準拠しているため、商用プロジェクトを含む幅広い用途で自由に使用することができる。

toml++の主要なクラス

toml++ライブラリの主要クラスを以下に示す。

  • toml::table
    TOMLのキー・値のペアを表現する中心的なクラスである。
    std::mapに似た動作をしており、TOMLドキュメント全体や入れ子になったテーブルの表現に使用する。

  • toml::array
    TOMLの配列を表現するクラスであり、std::vectorに類似している。
    異なる型の要素を含むことができる柔軟な配列である。

  • toml::value
    TOMLの任意の値 (文字列、整数、浮動小数点数、ブーリアン、日付 / 時刻、配列、テーブル) を表現できる汎用的なクラスである。
    型安全な方法で値を保持して、必要に応じて型変換を行う。

  • toml::date
  • toml::time
  • toml::date_time
    これらのクラスは日付と時刻の処理に使用する。
    TOMLの日付・時刻形式を精密に表現して、操作するためのものである。

  • toml::parse関数とtoml::formatterクラス
    パースとシリアライズの機能を提供する。
    toml::parseは、文字列やストリームからTOMLデータを読み込み、toml::formatterは、TOMLデータを文字列や出力ストリームに書き出す。

  • toml::parse_result
    エラーハンドリングに使用されるクラスである。
    パース操作の結果を表し、成功時にはパースされたデータを、失敗時にはエラー情報を提供する。

  • toml::node
    TOMLドキュメントの任意のノード (キー、値、テーブル、配列) を表現する抽象基底クラスである。
    型に依存しない汎用的な操作が可能になる。


toml++ライブラリのインストール

パッケージ管理システムからインストール
# RHEL
sudo dnf install tomlplusplus tomlplusplus-devel

# SUSE
-


ソースコードからインストール

toml++ライブラリのGithubにアクセスして、ソースコードをダウンロードする。
ダウンロードしたファイルを解凍する。

tar xf tomlplusplus-<バージョン>.tar.gz
cd tomlplusplus-<バージョン>


toml++ライブラリをビルドおよびインストールする。

mkdir build && cd build

# CMakeコマンドを使用する場合
cmake -DCMAKE_CXX_COMPILER=<G++ 8以降のG++> \
      -DCMAKE_BUILD_TYPE=Release           \
      -DCMAKE_INSTALL_PREFIX=<toml++ライブラリのインストールディレクトリ> \
      -DBUILD_EXAMPLES=ON                  \  # サンプルコードもインストールする場合
      ..
make -j $(nproc)
make install

# Meson & Ninjaを使用する場合
CXX=<G++ 8以降のG++> meson setup ./build                        \
                    -Dprefix=<toml++ライブラリのインストールディレクトリ> \
                    -Dbuild_examples=true  # サンプルコードもインストールする場合
ninja -C ./build -j $(nproc)
ninja -C ./build install


ライブラリの指定

Qtプロジェクトファイルを使用する場合
 # Qtプロジェクトファイル
 
 # pkg-configを使用してtoml++ライブラリを設定
 CONFIG += link_pkgconfig
 PKGCONFIG += tomlplusplus
 
 # pkg-configを使用しない場合
 LIBS += -ltomlplusplus


CMakeLists.txtファイルを使用する場合
 # CMakeLists.txtファイル
 
 # ...略
 
 find_package(PkgConfig REQUIRED)
 
 # toml+ライブラリの指定
 pkg_check_modules(TOMLPP REQUIRED tomlplusplus)
 
 # インクルードディレクトリの指定
 target_include_directories(${PROJECT_NAME} PRIVATE
   # ...略
   ${TOMLPP_INCLUDE_DIRS}
 )
 
 # ...略
 
 # ライブラリのリンク
 target_link_libraries(${PROJECT_NAME} PRIVATE
    # ...略
    ${TOMLPP_LIBRARIES}
 )
 
 # コンパイルオプションの設定
 target_compile_options(${PROJECT_NAME} PRIVATE
    # ...略
   ${TOMLPP_CFLAGS_OTHER}
 )



同期処理

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;
 }