--- nono/lib/config.h 2026/04/29 17:04:30 1.1 +++ nono/lib/config.h 2026/04/29 17:05:18 1.1.1.7 @@ -1,18 +1,24 @@ // // nono -// Copyright (C) 2018 isaki@NetBSD.org +// Copyright (C) 2020 nono project +// Licensed under nono-license.txt +// + +// +// 設定 // // 設定ファイルは、テキスト形式、行志向で順序を持たない key=value ペアの羅列、 // アプリケーションが書き戻しを行わないためユーザが任意にコメント行を入れる // ことが出来る、タイプのもの。 // -// 設定(Config)は次の3段階によって確定する。 -// c1. 初期値 +// 設定(Config)は次の4段階によって確定する。 +// c0. 初期値 // 項目はそれぞれ固有の初期値を持っている。ここでいう初期値は単なるゼロ // クリアではなく、その項目に最も自然な、あるいは極力問題なく動作するよう // 選択した値のこと。 -// c2. 設定ファイル +// c1. ~/.nono.cfg +// c2. VM ディレクトリの設定ファイル // 設定ファイルで指定された値はそれを上書きする。 // c3. コマンドライン引数 // コマンドライン引数で指定された値はそれを上書きする。 @@ -21,7 +27,7 @@ #pragma once -#include "header.h" +#include "mainapp.h" #include // 設定の1項目 @@ -37,15 +43,15 @@ class ConfigItem }; public: - ConfigItem() { }; - ConfigItem(const std::string& key_, const std::string& val_, + ConfigItem() { } + ConfigItem(const std::string& key_, const std::string& val_, VMCap vmcap_, from_t from_, const std::string& where_) { key = key_; value = val_; + vmcap = vmcap_; from = from_; where = where_; } - virtual ~ConfigItem() { }; // 値を文字列のまま取得する。 const std::string& AsString() const { return value; } @@ -56,6 +62,16 @@ class ConfigItem // なるので、それでもよければ使ってよい。 int AsInt() const { return atoi(value.c_str()); } + // 値を整数値として取得する。 + // 変換できたら true を返す。 + // 数値として評価出来ないときは false を返す。 + bool TryInt(int *val) const; + + // 値を double 値として取得する。 + // 変換できたら true を返す。 + // double 値として評価出来ないときは false を返す。 + bool TryDouble(double *val) const; + // デフォルト値を差し替える。 // この変数が FromInitial なら値(初期値)を val に差し替える。この時 // from は FromInitial のまま。 @@ -65,19 +81,28 @@ class ConfigItem // 問題のため、VM 種別によって初期値が決定する場合などはデバイスの // コンストラクタでこれを呼び出すこと。例えば mpu-clock など。 void SetDefault(const std::string& val); - void SetDefault(int val); + + // vmcap を取得する + VMCap GetVMCap() const { return vmcap; } // from を取得する from_t GetFrom() const { return from; } + // where を取得する + const std::string& GetWhere() const { return where; } + // この項目で "invalid argument" を warnx() で出力する void Err() const; // この項目での指定のエラーメッセージを warnx() で出力する void Err(const std::string& msg) const; - void Err(const char *fmt, ...) const; + void Err(const char *fmt, ...) const __printflike(2, 3); private: + static void PrintErr(ConfigItem::from_t from, const std::string& where, + const std::string& key, const std::string& value, + const std::string& msg); + // key が変数名、value が値。 // value はここでは文字列でありそれ以上の構造は持たないが、 // 整数値として解釈する或いはカンマ区切りにするなどは使う側の裁量。 @@ -86,8 +111,13 @@ class ConfigItem std::string key {}; std::string value {}; + // ケーパビリティ。 + // 機種確定後に、この機種に不要な変数は削除する。 + VMCap vmcap {}; + // from (と where) はこの変数の由来を示す。 - // o FromOption なら値は -V オプションで指定されたことを示す。 + // o FromOption なら値はコマンドラインオプションで指定されたことを示す。 + // この場合 where に "-V" とかが入っている。 // o FromConfig なら値は設定ファイルで指定されたことを示す。 // この場合 where に "ファイルパス:行番号" が入っている。 // o FromInitial なら値は初期値のままであることを示す。引数や @@ -102,7 +132,7 @@ class ConfigFile { public: ConfigFile(const std::string& filepath_); - virtual ~ConfigFile(); + ~ConfigFile(); // ファイルの読み込み。 // 成功すれば true を返す。失敗すればエラーを表示して false を返す。 @@ -123,29 +153,42 @@ class Config { public: Config(); - virtual ~Config(); + ~Config(); // 設定ファイルの内容で上書きする bool Update(const ConfigFile& file); // コマンドライン引数の内容で上書きする - bool Update(const std::vector& options); + bool Update(const std::string& line, const std::string& optname); // 内容を表示する - void Show() const; + void Show(bool all) const; - // key から ConfigItem を取得する。 - // key は必ず存在するので参照を返す。 + // key から ConfigItem を取得する。key は必ず存在するので参照を返す。 // 見付からなければ assert する。それはプログラムミスなので。 - const ConfigItem& Get(const std::string& key) const; - ConfigItem& Get(const std::string& key); + const ConfigItem& Find(const std::string& key) const; - private: - // 項目を追加 (初期状態用) - bool Add(const std::string& key); - bool Add(const std::string& key, int value); - bool Add(const std::string& key, const std::string& value); + // デフォルト値を差し替える。 + // key が見付からなければ assert する。それはプログラムミスなので。 + void SetDefault(const std::string& key, int value); + void SetDefault(const std::string& key, const std::string& value); + + // 項目を追加 + bool Add(const std::string& key, VMCap vmcap = VMCap::ALL); + bool Add(const std::string& key, int value, VMCap vmcap = VMCap::ALL); + bool Add(const std::string& key, const std::string& value, + VMCap vmcap = VMCap::ALL); + + // エイリアスを追加 + bool AddAlias(const std::string& alias, const std::string& key); + + // 項目を削除 + void Delete(const std::string& key); + + // 以降書き込み禁止にする (プログラムミスを避けるため) + bool Fix(); + private: // key から ConfigItem を返す。見付からなければ NULL を返す。 // (こっちは内部で変更するために使う) ConfigItem *FindItem(const std::string& key); @@ -154,12 +197,22 @@ class Config bool UpdateLine(const std::string& line, ConfigItem::from_t, const std::string& from); + // キーの正規名を返す + const std::string& GetCanonKey(const std::string& key) const; + // "key=val" 形式の行から key, val を取り出す。 static bool SplitKeyVal(std::string *keyp, std::string *valp, const std::string& line); // 設定項目の集合 std::vector list {}; + + // エイリアス(別名)の集合 + std::vector> aliases {}; + + // 設定はある時点までは追加更新可能だが、途中からは読み込み専用としたい。 + // プログラムミスを避けるため。 + bool fixed {}; }; -extern std::unique_ptr gConfig; +extern Config *gConfig;