Annotation of nono/lib/config.h, revision 1.1.1.13

1.1       root        1: //
                      2: // nono
1.1.1.2   root        3: // Copyright (C) 2020 nono project
                      4: // Licensed under nono-license.txt
1.1       root        5: //
                      6: 
1.1.1.4   root        7: //
                      8: // 設定
                      9: //
                     10: 
1.1       root       11: // 設定ファイルは、テキスト形式、行志向で順序を持たない key=value ペアの羅列、
                     12: // アプリケーションが書き戻しを行わないためユーザが任意にコメント行を入れる
                     13: // ことが出来る、タイプのもの。
                     14: //
1.1.1.6   root       15: // 設定(Config)は次の4段階によって確定する。
                     16: // c0. 初期値
1.1       root       17: //    項目はそれぞれ固有の初期値を持っている。ここでいう初期値は単なるゼロ
                     18: //    クリアではなく、その項目に最も自然な、あるいは極力問題なく動作するよう
                     19: //    選択した値のこと。
1.1.1.6   root       20: // c1. ~/.nono.cfg
                     21: // c2. VM ディレクトリの設定ファイル
1.1       root       22: //    設定ファイルで指定された値はそれを上書きする。
                     23: // c3. コマンドライン引数
                     24: //    コマンドライン引数で指定された値はそれを上書きする。
                     25: //
                     26: // おそらくたぶんすべての項目が例外なくこのように動作するようにしたい。
                     27: 
                     28: #pragma once
                     29: 
1.1.1.5   root       30: #include "mainapp.h"
1.1.1.12  root       31: #include <map>
1.1       root       32: #include <vector>
                     33: 
                     34: // 設定の1項目
                     35: class ConfigItem
                     36: {
                     37:        friend class Config;
                     38: 
                     39:  public:
                     40:        enum from_t {
                     41:                FromInitial = 0,        // 初期値
1.1.1.8   root       42:                FromHome,                       // 共通設定ファイル(~/.nono.cfg)で更新
                     43:                FromConfig,                     // VM 設定ファイルで更新
1.1       root       44:                FromOption,                     // コマンドライン引数で更新
1.1.1.9   root       45:                FromPerf,                       // --perf オプション(を展開したもの)で更新
1.1.1.11  root       46:                FromRunning,            // 実行中に更新
1.1       root       47:        };
                     48: 
                     49:  public:
1.1.1.2   root       50:        ConfigItem() { }
1.1.1.5   root       51:        ConfigItem(const std::string& key_, const std::string& val_, VMCap vmcap_,
1.1       root       52:                from_t from_, const std::string& where_) {
                     53:                key   = key_;
                     54:                value = val_;
1.1.1.5   root       55:                vmcap = vmcap_;
1.1       root       56:                from  = from_;
                     57:                where = where_;
                     58:        }
                     59: 
                     60:        // 値を文字列のまま取得する。
                     61:        const std::string& AsString() const { return value; }
                     62: 
1.1.1.13! root       63:        // 値をブール値として取得する。
        !            64:        // この関数はよく似たことをたびたびやるのを避けるために提供してある
        !            65:        // ただのユーティリティ関数。変換できない場合や空文字列の場合 false に
        !            66:        // なるので、それでもよければ使ってよい。
        !            67:        bool AsBool() const { return (bool)AsInt(); }
        !            68: 
1.1       root       69:        // 値を整数値として取得する。
                     70:        // この関数はよく似たことをたびたびやるのを避けるために提供してある
                     71:        // ただのユーティリティ関数。変換できない場合や空文字列の場合 0 に
                     72:        // なるので、それでもよければ使ってよい。
                     73:        int AsInt() const { return atoi(value.c_str()); }
                     74: 
1.1.1.4   root       75:        // 値を整数値として取得する。
                     76:        // 変換できたら true を返す。
                     77:        // 数値として評価出来ないときは false を返す。
                     78:        bool TryInt(int *val) const;
                     79: 
1.1.1.6   root       80:        // 値を double 値として取得する。
                     81:        // 変換できたら true を返す。
                     82:        // double 値として評価出来ないときは false を返す。
                     83:        bool TryDouble(double *val) const;
                     84: 
1.1.1.9   root       85:        // 値を固定小数点数として取得する。
                     86:        // 変換できたら true を返す。
                     87:        // 数値として評価出来ないときは false を返す。
                     88:        bool TryFixedDecimal(int *val, int digit) const;
                     89: 
1.1       root       90:        // デフォルト値を差し替える。
                     91:        // この変数が FromInitial なら値(初期値)を val に差し替える。この時
                     92:        // from は FromInitial のまま。
                     93:        // FromInitial でなければ (ユーザが値を上書きしていれば) 何もしない。
                     94:        // 本来は初期値設定 -> 設定ファイルやオプションで上書きの順に動作する
                     95:        // のが理想だが、設定ファイルを読まないと VM 種別が確定しないにわたま
                     96:        // 問題のため、VM 種別によって初期値が決定する場合などはデバイスの
                     97:        // コンストラクタでこれを呼び出すこと。例えば mpu-clock など。
                     98:        void SetDefault(const std::string& val);
                     99: 
1.1.1.5   root      100:        // vmcap を取得する
                    101:        VMCap GetVMCap() const { return vmcap; }
                    102: 
1.1       root      103:        // from を取得する
                    104:        from_t GetFrom() const { return from; }
                    105: 
1.1.1.6   root      106:        // where を取得する
                    107:        const std::string& GetWhere() const { return where; }
                    108: 
1.1.1.11  root      109:        // この項目で "Invalid argument" のエラーメッセージ文字列を返す。
                    110:        std::string ErrMsg() const;
                    111:        // この項目で指定のメッセージのエラーメッセージ文字列を返す。
                    112:        std::string ErrMsg(const char *fmt, ...) const __printflike(2, 3);
                    113:        std::string ErrMsg(const std::string& msg) const;
                    114: 
1.1       root      115:        // この項目で "invalid argument" を warnx() で出力する
                    116:        void Err() const;
                    117:        // この項目での指定のエラーメッセージを warnx() で出力する
1.1.1.2   root      118:        void Err(const char *fmt, ...) const __printflike(2, 3);
1.1.1.11  root      119:        void Err(const std::string& msg) const;
1.1       root      120: 
                    121:  private:
1.1.1.11  root      122:        static std::string ErrFrom(ConfigItem::from_t from,
                    123:                const std::string& where,
                    124:                const std::string& key, const std::string& value);
1.1.1.4   root      125: 
1.1       root      126:        // key が変数名、value が値。
                    127:        // value はここでは文字列でありそれ以上の構造は持たないが、
                    128:        // 整数値として解釈する或いはカンマ区切りにするなどは使う側の裁量。
                    129:        // value からは前後の空白は削除する。
                    130:        // またエスケープの類も今の所ない。
                    131:        std::string key {};
                    132:        std::string value {};
                    133: 
1.1.1.5   root      134:        // ケーパビリティ。
                    135:        // 機種確定後に、この機種に不要な変数は削除する。
                    136:        VMCap vmcap {};
                    137: 
1.1       root      138:        // from (と where) はこの変数の由来を示す。
1.1.1.6   root      139:        // o FromOption なら値はコマンドラインオプションで指定されたことを示す。
                    140:        //   この場合 where に "-V" とかが入っている。
1.1.1.8   root      141:        // o FromConfig, FromHome なら値は設定ファイルで指定されたことを示す。
1.1       root      142:        //   この場合 where に "ファイルパス:行番号" が入っている。
                    143:        // o FromInitial なら値は初期値のままであることを示す。引数や
                    144:        //   設定ファイルで値を指定した場合は例え初期値と同じ値を指定したと
                    145:        //   しても初期値扱いとはしない。
                    146:        from_t from {};
                    147:        std::string where {};
                    148: };
                    149: 
                    150: // 設定ファイル
                    151: class ConfigFile
                    152: {
                    153:  public:
1.1.1.8   root      154:        ConfigFile(const std::string& filepath_, ConfigItem::from_t from_);
1.1.1.6   root      155:        ~ConfigFile();
1.1       root      156: 
                    157:        // ファイルの読み込み。
                    158:        // 成功すれば true を返す。失敗すればエラーを表示して false を返す。
                    159:        bool Load();
                    160: 
                    161:        // パス
                    162:        std::string filepath {};
                    163: 
1.1.1.8   root      164:        // 設定元
                    165:        ConfigItem::from_t from {};
                    166: 
1.1       root      167:        // 読み込んだ行一覧
                    168:        // 行(改行と前後の空白を除く) と行番号(1から始まる)の pair。
                    169:        // コメント行や空行は取り除いてあるが、文法チェックはしていないので
                    170:        // 何か書いてある行の集合。
                    171:        std::vector<std::pair<std::string, int>> lines {};
                    172: };
                    173: 
                    174: // 設定
                    175: class Config
                    176: {
                    177:  public:
                    178:        Config();
1.1.1.6   root      179:        ~Config();
1.1       root      180: 
                    181:        // 設定ファイルの内容で上書きする
                    182:        bool Update(const ConfigFile& file);
                    183: 
                    184:        // コマンドライン引数の内容で上書きする
1.1.1.6   root      185:        bool Update(const std::string& line, const std::string& optname);
1.1       root      186: 
1.1.1.11  root      187:        // 実行中に動的に変更する
                    188:        bool UpdateRunning(const std::string& line);
                    189: 
1.1       root      190:        // 内容を表示する
1.1.1.2   root      191:        void Show(bool all) const;
1.1       root      192: 
1.1.1.2   root      193:        // key から ConfigItem を取得する。key は必ず存在するので参照を返す。
1.1       root      194:        // 見付からなければ assert する。それはプログラムミスなので。
1.1.1.2   root      195:        const ConfigItem& Find(const std::string& key) const;
1.1       root      196: 
1.1.1.2   root      197:        // デフォルト値を差し替える。
                    198:        // key が見付からなければ assert する。それはプログラムミスなので。
                    199:        void SetDefault(const std::string& key, int value);
                    200:        void SetDefault(const std::string& key, const std::string& value);
                    201: 
                    202:        // 項目を追加
1.1.1.5   root      203:        bool Add(const std::string& key, VMCap vmcap = VMCap::ALL);
                    204:        bool Add(const std::string& key, int value, VMCap vmcap = VMCap::ALL);
                    205:        bool Add(const std::string& key, const std::string& value,
                    206:                VMCap vmcap = VMCap::ALL);
1.1       root      207: 
1.1.1.7   root      208:        // エイリアスを追加
                    209:        bool AddAlias(const std::string& alias, const std::string& key);
                    210: 
1.1.1.12  root      211:        // 廃止項目を追加
                    212:        void AddObsolete(const std::string& old, const std::string& alter);
                    213: 
1.1.1.3   root      214:        // 項目を削除
                    215:        void Delete(const std::string& key);
                    216: 
1.1.1.2   root      217:        // 以降書き込み禁止にする (プログラムミスを避けるため)
1.1.1.6   root      218:        bool Fix();
1.1.1.2   root      219: 
                    220:  private:
1.1       root      221:        // key から ConfigItem を返す。見付からなければ NULL を返す。
                    222:        // (こっちは内部で変更するために使う)
                    223:        ConfigItem *FindItem(const std::string& key);
                    224: 
                    225:        // 更新1行分の共通処理
1.1.1.10  root      226:        bool UpdateLine(const std::string& line, ConfigItem::from_t from,
                    227:                const std::string& where);
1.1       root      228: 
1.1.1.7   root      229:        // キーの正規名を返す
                    230:        const std::string& GetCanonKey(const std::string& key) const;
                    231: 
1.1       root      232:        // "key=val" 形式の行から key, val を取り出す。
                    233:        static bool SplitKeyVal(std::string *keyp, std::string *valp,
                    234:                const std::string& line);
                    235: 
1.1.1.12  root      236:        // key が obsolete[] に含まれていれば true を返す。
                    237:        bool IsObsolete(const std::string& key) const {
                    238:                return (obsolete.find(key) != obsolete.end());
                    239:        }
                    240: 
1.1       root      241:        // 設定項目の集合
                    242:        std::vector<ConfigItem> list {};
1.1.1.2   root      243: 
1.1.1.7   root      244:        // エイリアス(別名)の集合
                    245:        std::vector<std::pair<std::string, std::string>> aliases {};
                    246: 
1.1.1.12  root      247:        // 廃止項目名の集合
                    248:        std::map<std::string, std::string> obsolete {};
                    249: 
1.1.1.2   root      250:        // 設定はある時点までは追加更新可能だが、途中からは読み込み専用としたい。
                    251:        // プログラムミスを避けるため。
                    252:        bool fixed {};
1.1       root      253: };
                    254: 
1.1.1.4   root      255: extern Config *gConfig;

unix.superglobalmegacorp.com

This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.