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