|
|
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;
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.