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