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