MochiuWiki : SUSE, EC, PCB
案内
メインページ
最近の更新
おまかせ表示
MediaWiki についてのヘルプ
ツール
リンク元
関連ページの更新状況
特別ページ
ページ情報
We ask for
Donations
検索
個人用ツール
ログイン
Toggle dark mode
名前空間
ページ
議論
表示
閲覧
ソースを閲覧
履歴を表示
Qtの基礎 - TOMLのソースを表示
提供: MochiuWiki : SUSE, EC, PCB
←
Qtの基礎 - TOML
あなたには「このページの編集」を行う権限がありません。理由は以下の通りです:
この操作は、次のグループのいずれかに属する利用者のみが実行できます:
管理者
、new-group。
このページのソースの閲覧やコピーができます。
== 概要 == TOML (Tom's Obvious, Minimal Language) は、設定ファイルフォーマットとして設計された。<br> QtでTOMLを使用することは、アプリケーションの設定や構成を管理する上で有効である。<br> <br> TOMLの特徴として、人間が読み書きしやすい形式であることが挙げられる。<br> キーと値のペアを基本構造とし、階層的なデータ構造も表現することができる。<br> <br> 日付や時刻、真偽値、数値等、様々なデータ型をサポートしている。<br> <br> Qtには組み込みのTOMLパーサーが存在しないため、サードパーティ製ライブラリを使用する必要がある。<br> 一般的に、<u>toml11ライブラリ</u>や<u>toml++ライブラリ</u>等のサードパーティ製ライブラリがよく使用されている。<br> これらのライブラリを使用することにより、TOMLファイルの読み込み、書き込み、データの解析が容易になる。<br> <br> TOMLの構文は、基本的な形式は<code><キー> = <値></code>のペアで記述する。<br> セクションを使用してデータをグループ化することもでき、これはブラケット<code>[]</code>で囲むことで表現する。<br> <br> TOMLを使用するメリットとして、設定の管理が容易になることが挙げられる。<br> 例えば、アプリケーションの起動時にTOMLファイルから設定を読み込み、実行時に変更された設定をTOMLファイルに書き込むような使用方法が考えられる。<br> <br> TOMLは他の設定ファイル形式 (JSONやYAML等) と比較して、より直感的で読みやすい構文を持っている。<br> 特に複雑な階層構造を持つ設定データを扱う場合に、そのメリットが発揮される。<br> <br> ただし、TOMLを使用する場合は、選択したライブラリの依存関係管理やパフォーマンスへの影響を考慮する必要がある。<br> <br><br> == TOMLの構文 == TOMLファイルの主な構文要素を以下に示す。<br> <br> * キーと値のペア *: 基本的な形式は、<code><キー名> = <値></code> である。 *: 例: <code>name = "TOML Example"</code> *: <br> * 文字列 ** 基本文字列 **: ダブルクォートで囲む **: <code>"Hello"</code> ** リテラル文字列 **: シングルクォートで囲む **: <code>'C:\Users\username'</code> *: <br> * 数値 ** 整数 **: <code>42</code> ** 浮動小数点 **: <code>3.14</code> *: <br> * ブーリアン *: true または false *: <br> * 日付と時刻 *: ISO 8601形式を使用する。 *: 例: <code>date = 2023-03-27T15:32:00Z</code> *: <br> * 配列 *: 角括弧で囲む。 *: 例: <code>colors = [ "red", "yellow", "green" ]</code> *: <br> * テーブル (セクション) *: 角括弧で囲んだ名前で定義する。 *: 例: *: <syntaxhighlight lang="toml"> [database] server = "192.168.1.1" ports = [ 8001, 8001, 8002 ] </syntaxhighlight> *: <br> * インラインテーブル *: 中括弧で囲む。 *: 例: <code>point = { x = 1, y = 2 }</code> *: <br> * テーブルの配列 *: 2重の角括弧で定義する。 *: 例: *: <syntaxhighlight lang="toml"> [[fruits]] name = "apple" [[fruits]] name = "banana" </syntaxhighlight> *: <br> * コメント *: シャープ記号 (<code>#</code>) を使用する。 <br><br> == TOMLファイルの例 == <syntaxhighlight lang="toml"> # config.tomlファイル title = "設定ファイル" # トップレベルのキー [user] # ユーザ情報のセクション name = "山田太郎" age = 30 email = "yamada@example.com" [application] # アプリケーション設定のセクション version = "1.0.0" debug_mode = false [database] # データベース接続情報のセクション host = "localhost" port = 5432 username = "admin" password = "secret" [features] # 機能のオン / オフを制御するセクション enabled = ["login", "logout", "dashboard"] disabled = ["admin_panel"] [logging] # ロギング設定のセクション level = "info" file = "/var/log/app.log" [[servers]] # サーバ情報の配列 ip = "192.168.1.1" role = "frontend" [[servers]] # サーバ情報の配列 ip = "192.168.1.2" role = "backend" </syntaxhighlight> <br><br> == toml++ライブラリ == ==== toml++ライブラリとは ==== toml++ライブラリは、C++ 17以降で記述されたヘッダファイルのみのTOMパーサーおよびシリアライザーライブラリである。<br> このライブラリは、TOML v1.0.0仕様に完全準拠しており、使いやすい設計が特徴である。<br> <br> 主な特徴として、テンプレートベースの設計が挙げられる。<br> これにより、コンパイル時の型チェックが可能となり、実行時のパフォーマンスが向上する。<br> また、例外を使用しないエラーハンドリングをサポートしており、例外が禁止されている環境でも問題なく使用できる。<br> <br> toml++は、UTF-8エンコーディングを完全にサポートしており、国際化されたアプリケーションでの使用が容易になる。<br> さらに、コメントの保持機能も備えており、TOMLファイルを読み込んで修正した後、元のコメントを保持したまま書き出すことができる。<br> <br> toml++ライブラリは、単一ヘッダファイル版と複数ヘッダファイル版の両方が提供されており、プロジェクトの要件に応じて適切なものを選択することができる。<br> <br> toml++ライブラリの使用例としては、設定ファイルの読み書き、データのシリアライズ / デシリアライズ、構造化されたデータの保存等が挙げられる。<br> C++の標準ライブラリと密接に統合されているため、std::stringクラスやその他のSTLコンテナとの相互運用性が高い。<br> <br> パフォーマンス面では、toml++ライブラリは他の多くのTOMLパーサーよりも高速であることが報告されている。<br> 大規模なTOMLファイルを扱う場合や、頻繁なパース / シリアライズ操作が必要なアプリケーションで特に威力を発揮する。<br> <br> ドキュメンテーションも充実しており、GitHubリポジトリには詳細な使用方法や設定オプションが記載されている。<br> また、豊富な例やチュートリアルも提供されているため、初めて使用する開発者でも迅速に習得することができる。<br> <br> ==== toml++ライブラリのライセンス ==== toml++ライブラリのライセンスはMITライセンスに準拠しているため、商用プロジェクトを含む幅広い用途で自由に使用することができる。<br> <br> ==== toml++の主要なクラス ==== toml++ライブラリの主要クラスを以下に示す。<br> <br> * toml::table *: TOMLのキー・値のペアを表現する中心的なクラスである。 *: std::mapに似た動作をしており、TOMLドキュメント全体や入れ子になったテーブルの表現に使用する。 *: <br> * toml::array *: TOMLの配列を表現するクラスであり、std::vectorに類似している。 *: 異なる型の要素を含むことができる柔軟な配列である。 *: <br> * toml::value *: TOMLの任意の値 (文字列、整数、浮動小数点数、ブーリアン、日付 / 時刻、配列、テーブル) を表現できる汎用的なクラスである。 *: 型安全な方法で値を保持して、必要に応じて型変換を行う。 *: <br> * toml::date * toml::time * toml::date_time *: これらのクラスは日付と時刻の処理に使用する。 *: TOMLの日付・時刻形式を精密に表現して、操作するためのものである。 *: <br> * toml::parse関数とtoml::formatterクラス *: パースとシリアライズの機能を提供する。 *: toml::parseは、文字列やストリームからTOMLデータを読み込み、toml::formatterは、TOMLデータを文字列や出力ストリームに書き出す。 *: <br> * toml::parse_result *: エラーハンドリングに使用されるクラスである。 *: パース操作の結果を表し、成功時にはパースされたデータを、失敗時にはエラー情報を提供する。 *: <br> * toml::node *: TOMLドキュメントの任意のノード (キー、値、テーブル、配列) を表現する抽象基底クラスである。 *: 型に依存しない汎用的な操作が可能になる。 <br> ==== toml++ライブラリのインストール ==== ===== パッケージ管理システムからインストール ===== # RHEL sudo dnf install tomlplusplus tomlplusplus-devel # SUSE - <br> ===== ソースコードからインストール ===== [https://github.com/marzer/tomlplusplus toml++ライブラリのGithub]にアクセスして、ソースコードをダウンロードする。<br> ダウンロードしたファイルを解凍する。<br> tar xf tomlplusplus-<バージョン>.tar.gz cd tomlplusplus-<バージョン> <br> toml++ライブラリをビルドおよびインストールする。<br> 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 <br> ==== ライブラリの指定 ==== ===== Qtプロジェクトファイルを使用する場合 ===== <syntaxhighlight lang="make"> # Qtプロジェクトファイル # pkg-configを使用してtoml++ライブラリを設定 CONFIG += link_pkgconfig PKGCONFIG += tomlplusplus # pkg-configを使用しない場合 LIBS += -ltomlplusplus </syntaxhighlight> <br> ===== CMakeLists.txtファイルを使用する場合 ===== <syntaxhighlight lang="cmake"> # 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} ) </syntaxhighlight> <br> ==== 同期処理 ==== ===== TOMLの読み込み ===== 以下の例では、toml++ライブラリを使用して、TOMLファイルを読み込んでいる。<br> toml++ライブラリを使用する場合は、プロジェクトにtoml++ライブラリをリンクする必要がある。<br> <br> <syntaxhighlight lang="c++"> #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()); } } }; </syntaxhighlight> <br> 以下の例では、上記のクラスを使用してTOMLファイルを読み込んでいる。<br> <br> <syntaxhighlight lang="c++"> #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; } </syntaxhighlight> <br> ===== TOMLファイルの書き込み ===== 以下の例では、toml++ライブラリを使用して、TOMLファイルを書き込んでいる。<br> toml++ライブラリを使用する場合は、プロジェクトにtoml++ライブラリをリンクする必要がある。<br> <br> <syntaxhighlight lang="c++"> #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; } }; </syntaxhighlight> <br> 以下の例では、上記のクラスを使用してTOMLファイルを書き込んでいる。<br> <br> <syntaxhighlight lang="c++"> #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; } </syntaxhighlight> <br> ==== 非同期処理 ==== ===== TOMLの読み込み ===== 以下の例では、toml++ライブラリを使用して、非同期でTOMLファイルを読み込んでいる。<br> toml++ライブラリを使用する場合は、プロジェクトにtoml++ライブラリをリンクする必要がある。<br> <br> <syntaxhighlight lang="c++"> // AsyncTomlHandler.hファイル #include <QObject> #include <QFile> #include <QTextStream> #include <QBuffer> #include <QFuture> #include <QtConcurrent> #include <stdexcept> #include <toml++/toml.h> class AsyncTomlHandler : public QObject { Q_OBJECT private: toml::table readTomlFromDevice(QIODevice* device) { std::unique_ptr<QIODevice> devicePtr(device); // デバイスの自動クリーンアップを保証 return readTomlStream(device); } public: explicit AsyncTomlHandler(QObject *parent = nullptr) : QObject(parent) {} // TOMLファイルを非同期で読み込む QFuture<toml::table> readTomlAsync(const QString& filename) { return QtConcurrent::run([this, filename]() { return this->readTomlFromDevice(new QFile(filename)); }); } // TOMLデータをストリームから読み込む toml::table readTomlStream(QIODevice* device) { if (!device->open(QIODevice::ReadOnly | QIODevice::Text)) { throw std::runtime_error("デバイスを開けません"); } QTextStream in(device); QString content = in.readAll(); device->close(); try { return toml::parse(content.toStdString()); } catch (const toml::parse_error &err) { throw std::runtime_error(QString("TOMLデータの解析エラー: %1").arg(err.description().c_str()).toStdString()); } } // メモリ上のTOMLデータを読み込む toml::table readTomlFromMemory(const QByteArray& data) { QBuffer buffer; buffer.setData(data); return readTomlStream(&buffer); } }; </syntaxhighlight> <br> 以下の例では、上記のクラスを使用してTOMLファイルを非同期で読み込んでいる。<br> <br> <syntaxhighlight lang="c++"> #include <QCoreApplication> #include <QFuture> #include <QFutureWatcher> #include <QDebug> #include "AsyncTomlHandler.h" int main(int argc, char *argv[]) { QCoreApplication a(argc, argv); AsyncTomlHandler handler; // 非同期でTOMLファイルを読み込む QFuture<toml::table> readFuture = handler.readTomlAsync("config.toml"); QFutureWatcher<toml::table> readWatcher; QObject::connect(&readWatcher, &QFutureWatcher<toml::table>::finished, [&]() { try { toml::table data = readWatcher.result(); qDebug() << "Name:" << QString::fromStdString(data["name"].value_or("")); qDebug() << "Age:" << data["age"].value_or(0); } catch (const std::exception &e) { qCritical() << "エラー: " << e.what(); QCoreApplication::quit(); } }); readWatcher.setFuture(readFuture); return a.exec(); } </syntaxhighlight> <br> ===== TOMLファイルの書き込み ===== 以下の例では、toml++ライブラリを使用して、非同期でTOMLファイルを書き込んでいる。<br> toml++ライブラリを使用する場合は、プロジェクトにtoml++ライブラリをリンクする必要がある。<br> <br> <syntaxhighlight lang="c++"> // AsyncTomlHandler.hファイル #include <QObject> #include <QFile> #include <QTextStream> #include <QBuffer> #include <QFuture> #include <QtConcurrent> #include <stdexcept> #include <toml++/toml.h> class AsyncTomlHandler : public QObject { Q_OBJECT private: toml::table readTomlFromDevice(QIODevice *device) { std::unique_ptr<QIODevice> devicePtr(device); // デバイスの自動クリーンアップを保証 return readTomlStream(device); } void writeTomlToDevice(QIODevice *device, const toml::table &data) { std::unique_ptr<QIODevice> devicePtr(device); // デバイスの自動クリーンアップを保証 writeTomlStream(device, data); } public: explicit AsyncTomlHandler(QObject *parent = nullptr) : QObject(parent) {} // TOMLファイルを非同期で読み込む QFuture<toml::table> readTomlAsync(const QString &filename) { return QtConcurrent::run([this, filename]() { return this->readTomlFromDevice(new QFile(filename)); }); } // TOMLデータを非同期でファイルに書き込む QFuture<void> writeTomlAsync(const QString &filename, const toml::table &data) { return QtConcurrent::run([this, filename, data]() { this->writeTomlToDevice(new QFile(filename), data); }); } // TOMLデータをストリームから読み込む toml::table readTomlStream(QIODevice *device) { if (!device->open(QIODevice::ReadOnly | QIODevice::Text)) { throw std::runtime_error("デバイスを開けません"); } QTextStream in(device); QString content = in.readAll(); device->close(); try { return toml::parse(content.toStdString()); } catch (const toml::parse_error &err) { throw std::runtime_error(QString("TOMLデータの解析エラー: %1").arg(err.description().c_str()).toStdString()); } } // TOMLデータをストリームに書き込む void writeTomlStream(QIODevice *device, const toml::table &data) { if (!device->open(QIODevice::WriteOnly | QIODevice::Text)) { throw std::runtime_error("デバイスを開けません"); } QTextStream out(device); out << QString::fromStdString(toml::toml_formatter(data).format()); device->close(); } // メモリ上のTOMLデータを読み込む toml::table readTomlFromMemory(const QByteArray &data) { QBuffer buffer; buffer.setData(data); return readTomlStream(&buffer); } // メモリ上にTOMLデータを書き込む QByteArray writeTomlToMemory(const toml::table &data) { QBuffer buffer; writeTomlStream(&buffer, data); return buffer.buffer(); } }; </syntaxhighlight> <br> 以下の例では、上記のクラスを使用して、非同期でTOMLファイルを書き込んでいる。<br> <br> <syntaxhighlight lang="c++"> #include <QCoreApplication> #include <QFuture> #include <QFutureWatcher> #include <QDebug> #include "AsyncTomlHandler.h" int main(int argc, char *argv[]) { QCoreApplication a(argc, argv); AsyncTomlHandler handler; // 非同期でTOMLファイルを読み込む QFuture<toml::table> readFuture = handler.readTomlAsync("config.toml"); QFutureWatcher<toml::table> readWatcher; QObject::connect(&readWatcher, &QFutureWatcher<toml::table>::finished, [&]() { try { toml::table data = readWatcher.result(); qDebug() << "Name:" << QString::fromStdString(data["name"].value_or("")); qDebug() << "Age:" << data["age"].value_or(0); // データを変更 data["location"] = "Tokyo"; // 非同期で変更したデータを書き込む QFuture<void> writeFuture = handler.writeTomlAsync("config_updated.toml", data); QFutureWatcher<void> writeWatcher; QObject::connect(&writeWatcher, &QFutureWatcher<void>::finished, []() { qDebug() << "書き込み完了"; QCoreApplication::quit(); }); writeWatcher.setFuture(writeFuture); } catch (const std::exception &e) { qCritical() << "エラー:" << e.what(); QCoreApplication::quit(); } }); readWatcher.setFuture(readFuture); return a.exec(); } </syntaxhighlight> <br> ===== TOMLファイルの書き込み : メモリ操作 (ストリーミング処理) ===== 以下の例では、toml++ライブラリを使用して、メモリ上のTOMLデータを書き込んでいる。<br> toml++ライブラリを使用する場合は、プロジェクトにtoml++ライブラリをリンクする必要がある。<br> <br> # メモリ上のTOMLデータを読み込む。 # 読み込んだデータを表示して、一部のデータを変更する。 # 変更したデータをメモリに書き込み、結果を表示する。 <br> <syntaxhighlight lang="c++"> #include <QCoreApplication> #include <QDebug> #include "AsyncTomlHandler.h" int main(int argc, char *argv[]) { QCoreApplication a(argc, argv); AsyncTomlHandler handler; // メモリ上のTOMLデータを定義 QByteArray tomlData = R"( title = "TOMLサンプル" [owner] name = "山田太郎" age = 30 [database] enabled = true ports = [ 8000, 8001, 8002 ] data = [ ["delta", "phi"], [3.14] ] temp_targets = { cpu = 79.5, case = 72.0 } )"; try { // メモリからTOMLデータを読み込む toml::table data = handler.readTomlFromMemory(tomlData); // 読み込んだデータを表示 qDebug() << "メモリから読み込んだTOMLデータ:"; qDebug() << "タイトル:" << QString::fromStdString(data["title"].value_or("")); qDebug() << "オーナー名:" << QString::fromStdString(data["owner"]["name"].value_or("")); qDebug() << "オーナー年齢:" << data["owner"]["age"].value_or(0); qDebug() << "データベース有効:" << data["database"]["enabled"].value_or(false); // データを変更 data["owner"]["location"] = "東京"; data["database"]["version"] = "1.0.0"; // 変更したデータをメモリに書き込む QByteArray updatedData = handler.writeTomlToMemory(data); // 更新されたデータを表示 qDebug() << "更新されたTOMLデータ:"; qDebug() << updatedData; // 更新されたデータを再度読み込んで確認 toml::table updatedTable = handler.readTomlFromMemory(updatedData); qDebug() << "更新後のデータ確認:"; qDebug() << "オーナー所在地:" << QString::fromStdString(updatedTable["owner"]["location"].value_or("")); qDebug() << "データベースバージョン:" << QString::fromStdString(updatedTable["database"]["version"].value_or("")); } catch (const std::exception &e) { qCritical() << "エラー: " << e.what(); } QCoreApplication::quit(); return a.exec(); } </syntaxhighlight> <br><br> __FORCETOC__ [[カテゴリ:Qt]]
Qtの基礎 - TOML
に戻る。
案内
メインページ
最近の更新
おまかせ表示
MediaWiki についてのヘルプ
ツール
リンク元
関連ページの更新状況
特別ページ
ページ情報
We ask for
Donations
Collapse