9 * @brief フラグ集合を扱う、FlagGroupクラス
11 * @tparam FlagType 扱うフラグ集合を定義したenum class型
13 template <typename FlagType>
17 static constexpr auto FLAG_TYPE_MAX = static_cast<size_t>(FlagType::MAX);
21 * @brief フラグ集合に含まれるフラグの種類数を返す
23 * @return constexpr size_t フラグ集合に含まれるフラグの種類数
25 constexpr size_t size() const noexcept
31 * @brief FlagGroupクラスのデフォルトコンストラクタ
33 * すべてのフラグがOFFの状態のFlagGroupクラスのインスタンスを生成する
35 FlagGroup<FlagType>() = default;
38 * @brief FlagGroupクラスのコンストラクタ
40 * initializer_listで指定したフラグがON、それ以外はOFFの状態の
41 * FlagGroupクラスのインスタンスを生成する
43 * @param il ONの状態で生成するフラグを指定した initializer_list
45 FlagGroup<FlagType>(std::initializer_list<FlagType> il)
51 * @brief FlagGroupクラスのコンストラクタ
53 * 入力イテレータで指定した範囲のリストに含まれるフラグがON、
54 * それ以外のフラグがOFFの状態のFlagGroupクラスのインスタンスを生成する
56 * @tparam InputIter 入力イテレータの型
57 * @param first 範囲の開始位置を示す入力イテレータ
58 * @param last 範囲の終了位置を示す入力イテレータ
60 template <typename InputIter>
61 FlagGroup<FlagType>(InputIter first, InputIter last)
67 * @brief フラグ集合に含まれるフラグをすべてOFFにする
69 * @return FlagGroup<FlagType>& *thisを返す
71 FlagGroup<FlagType> &clear() noexcept
78 * @brief 指定したフラグを指定した値にセットする
80 * @param flag 値をセットするフラグを指定する
81 * @param val セットする値。trueならフラグをON、falseならフラグをOFFにする。
82 * 引数を省略した場合はフラグをONにする。
83 * @return FlagGroup<FlagType>& *thisを返す
85 FlagGroup<FlagType> &set(FlagType flag, bool val = true)
87 bs_.set(static_cast<size_t>(flag), val);
92 * @brief 入力イテレータで指定した範囲のリストに含まれるフラグをONにする
94 * @tparam InputIter 入力イテレータの型
95 * @param first 範囲の開始位置を示す入力イテレータ
96 * @param last 範囲の終了位置を示す入力イテレータ
97 * @return FlagGroup<FlagType>& *thisを返す
99 template <typename InputIter>
100 FlagGroup<FlagType> &set(InputIter first, InputIter last)
102 static_assert(std::is_same<typename std::iterator_traits<InputIter>::value_type, FlagType>::value, "Iterator value type is invalid");
104 std::for_each(first, last, [this](FlagType t) { set(t); });
109 * @brief 指定したFlagGroupのインスンタンスのONになっているフラグをONにする
111 * @param rhs ONにするフラグがONになっているFlagGroupのインスタンス
112 * @return FlagGroup<FlagType>& *thisを返す
114 FlagGroup<FlagType> &set(const FlagGroup<FlagType> &rhs)
121 * @brief 指定したinitializer_listに含まれるフラグをONにする
123 * @param list ONにするフラグを列挙したinitializer_list
124 * @return FlagGroup<FlagType>& *thisを返す
126 FlagGroup<FlagType> &set(std::initializer_list<FlagType> list)
128 return set(std::begin(list), std::end(list));
132 * @brief 指定したフラグをOFFにする
134 * @param flag OFFにするフラグを指定する
135 * @return FlagGroup<FlagType>& *thisを返す
137 FlagGroup<FlagType> &reset(FlagType flag)
139 bs_.reset(static_cast<size_t>(flag));
144 * @brief 入力イテレータで指定した範囲のリストに含まれるフラグをOFFにする
146 * @tparam InputIter 入力イテレータの型
147 * @param first 範囲の開始位置を示す入力イテレータ
148 * @param last 範囲の終了位置を示す入力イテレータ
149 * @return FlagGroup<FlagType>& *thisを返す
151 template <typename InputIter>
152 FlagGroup<FlagType> &reset(InputIter first, InputIter last)
154 static_assert(std::is_same<typename std::iterator_traits<InputIter>::value_type, FlagType>::value, "Iterator value type is invalid");
156 std::for_each(first, last, [this](FlagType t) { reset(t); });
161 * @brief 指定したFlagGroupのインスンタンスのONになっているフラグをOFFにする
163 * @param rhs OFFにするフラグがONになっているFlagGroupのインスタンス
164 * @return FlagGroup<FlagType>& *thisを返す
166 FlagGroup<FlagType> &reset(const FlagGroup<FlagType> &rhs)
173 * @brief 指定したinitializer_listに含まれるフラグをOFFにする
175 * @param list OFFにするフラグを列挙したinitializer_list
176 * @return FlagGroup<FlagType>& *thisを返す
178 FlagGroup<FlagType> &reset(std::initializer_list<FlagType> list)
180 return reset(std::begin(list), std::end(list));
184 * @brief 指定したフラグがONかOFFか調べる
186 * @param f 調べるフラグを指定する
187 * @return bool 指定したフラグがONならtrue、OFFならfalse
189 bool has(FlagType f) const
191 return bs_.test(static_cast<size_t>(f));
195 * @brief 指定したフラグがOFFかONか調べる
197 * @param f 調べるフラグを指定する
198 * @return bool 指定したフラグがOFFならtrue、ONならfalse
200 bool has_not(FlagType f) const
206 * @brief フラグ集合のいずれかのフラグがONかどうかを調べる
208 * @return bool フラグ集合のいずれかのフラグがONならtrue
209 * フラグ集合のすべてのフラグがOFFならfalse
211 bool any() const noexcept
217 * @brief フラグ集合のすべてのフラグがOFFかどうかを調べる
219 * @return bool フラグ集合のすべてのフラグがOFFならtrue
220 * フラグ集合のいずれかのフラグがONならfalse
222 bool none() const noexcept
228 * @brief 入力イテレータで指定した範囲のリストに含まれるフラグがすべてONかどうかを調べる
230 * @tparam InputIter 入力イテレータの型
231 * @param first 範囲の開始位置を示す入力イテレータ
232 * @param last 範囲の終了位置を示す入力イテレータ
233 * @return bool すべてのフラグがONであればtrue、そうでなければfalse
235 template <typename InputIter>
236 bool has_all_of(InputIter first, InputIter last) const
238 static_assert(std::is_same<typename std::iterator_traits<InputIter>::value_type, FlagType>::value, "Iterator value type is invalid");
240 return std::all_of(first, last, [this](FlagType f) { return has(f); });
244 * @brief 指定したinitializer_listに含まれるフラグがすべてONかどうかを調べる
246 * @param list 調べるフラグを列挙したinitializer_list
247 * @return bool すべてのフラグがONであればtrue、そうでなければfalse
249 bool has_all_of(std::initializer_list<FlagType> list) const
251 return has_all_of(std::begin(list), std::end(list));
255 * @brief 引数で指定したFlagGroupのインスンタンスのONになっているフラグがすべてONかどうかを調べる
257 * @param rhs FlagGroupのインスタンス
258 * @return bool すべてのフラグがONであればtrue、そうでなければfalse
260 bool has_all_of(const FlagGroup<FlagType> &rhs) const
262 return (bs_ & rhs.bs_) == rhs.bs_;
266 * @brief 入力イテレータで指定した範囲のリストに含まれるフラグのいずれかがONかどうかを調べる
268 * @tparam InputIter 入力イテレータの型
269 * @param first 範囲の開始位置を示す入力イテレータ
270 * @param last 範囲の終了位置を示す入力イテレータ
271 * @return bool いずれかのフラグがONであればtrue、そうでなければfalse
273 template <typename InputIter>
274 bool has_any_of(InputIter first, InputIter last) const
276 static_assert(std::is_same<typename std::iterator_traits<InputIter>::value_type, FlagType>::value, "Iterator value type is invalid");
278 return std::any_of(first, last, [this](FlagType f) { return has(f); });
282 * @brief 指定したinitializer_listに含まれるフラグのいずれかがONかどうかを調べる
284 * @param list 調べるフラグを列挙したinitializer_list
285 * @return bool いずれかのフラグがONであればtrue、そうでなければfalse
287 bool has_any_of(std::initializer_list<FlagType> list) const
289 return has_any_of(std::begin(list), std::end(list));
293 * @brief 引数で指定したFlagGroupのインスンタンスのONになっているフラグのいずれかがONかどうかを調べる
295 * @param rhs FlagGroupのインスタンス
296 * @return bool いずれかのフラグがONであればtrue、そうでなければfalse
298 bool has_any_of(const FlagGroup<FlagType> &rhs) const
300 return (bs_ & rhs.bs_) != 0;
304 * @brief 入力イテレータで指定した範囲のリストに含まれるフラグがすべてOFFかどうかを調べる
306 * @tparam InputIter 入力イテレータの型
307 * @param first 範囲の開始位置を示す入力イテレータ
308 * @param last 範囲の終了位置を示す入力イテレータ
309 * @return bool すべてのフラグがOFFであればtrue、そうでなければfalse
311 template <typename InputIter>
312 bool has_none_of(InputIter first, InputIter last) const
314 static_assert(std::is_same<typename std::iterator_traits<InputIter>::value_type, FlagType>::value, "Iterator value type is invalid");
316 return !has_any_of(first, last);
320 * @brief 指定したinitializer_listに含まれるフラグがすべてOFFかどうかを調べる
322 * @param list 調べるフラグを列挙したinitializer_list
323 * @return bool すべてのフラグがOFFであればtrue、そうでなければfalse
325 bool has_none_of(std::initializer_list<FlagType> list) const
327 return !has_any_of(list);
331 * @brief 引数で指定したFlagGroupのインスンタンスのONになっているフラグがすべてOFFかどうかを調べる
333 * @param rhs FlagGroupのインスタンス
334 * @return bool すべてのフラグがOFFであればtrue、そうでなければfalse
336 bool has_none_of(const FlagGroup<FlagType> &rhs) const
338 return !has_any_of(rhs);
342 * @brief フラグ集合のONになっているフラグの数を返す
344 * @return size_t ONになっているフラグの数
346 size_t count() const noexcept
352 * @brief フラグ集合の状態を0と1で表した文字列を返す
354 * フラグ集合の上位番号から順に、フラグがONなら1、OFFなら0で表した文字列を返す。
355 * 例: 5つのフラグ集合で、0:ON、1:OFF、2:OFF、3:ON、4:OFFの場合、"01001"
357 * @return std::string フラグ集合の状態を表した文字列
359 std::string str() const
361 return bs_.to_string();
365 * @brief セーブファイルからフラグ集合を読み出す
367 * @param fg 読み出したフラグ集合を格納するFlagGroupインスタンスの参照
368 * @param rd_byte_func セーブファイルから1バイトデータを読み出す関数(rd_byte)へのポインタ
370 friend void rd_FlagGroup(FlagGroup<FlagType> &fg, std::function<void(uint8_t *)> rd_byte_func)
372 uint8_t tmp_l, tmp_h;
373 rd_byte_func(&tmp_l);
374 rd_byte_func(&tmp_h);
375 const auto fg_size = static_cast<uint16_t>((tmp_h << 8) | tmp_l);
377 for (int i = 0; i < fg_size; i++) {
379 rd_byte_func(&flag_byte);
380 std::bitset<8> flag_bits(flag_byte);
381 for (int j = 0; j < 8; j++) {
382 const size_t pos = i * 8 + j;
383 if (pos < fg.bs_.size()) {
384 fg.bs_[pos] = flag_bits[j];
391 * @brief セーブファイルにフラグ集合を書き込む
393 * @param fg 書き込むフラグ集合を保持したFlagGroupインスタンスの参照
394 * @param wr_byte_func セーブファイルに1バイトデータを書き込む関数(wr_byte)へのポインタ
396 friend void wr_FlagGroup(const FlagGroup<FlagType> &fg, std::function<void(uint8_t)> wr_byte_func)
398 const auto fg_size = static_cast<uint16_t>((fg.bs_.size() + 7) / 8);
399 wr_byte_func(fg_size & 0xff);
400 wr_byte_func((fg_size >> 8) & 0xff);
402 for (int i = 0; i < fg_size; i++) {
403 std::bitset<8> flag_bits;
404 for (int j = 0; j < 8; j++) {
405 const size_t pos = i * 8 + j;
406 if (pos < fg.bs_.size()) {
407 flag_bits[j] = fg.bs_[pos];
410 wr_byte_func(flag_bits.to_ulong() & 0xff);
415 * @brief 文字列からフラグへのマップを指定した検索キーで検索し、
416 * 見つかった場合はフラグ集合に該当するフラグをセットする
418 * @tparam Map std::map<string_view, FlagType> もしくは std::unordered_map<string_view, FlagType>
419 * @param fg フラグをセットするフラグ集合
420 * @param dict 文字列からフラグへのマップ
421 * @param what マップの検索キー
422 * @return bool 検索キーでフラグが見つかり、フラグをセットした場合 true
425 template <typename Map>
426 static bool grab_one_flag(FlagGroup<FlagType> &fg, const Map &dict, std::string_view what)
428 auto it = dict.find(what);
429 if (it == dict.end())
438 * @brief 指定したフラグ位置へのアクセスを提供するプロキシクラス
442 reference(std::bitset<FlagGroup::FLAG_TYPE_MAX> &flags, size_t pos)
448 reference &operator=(const reference &rhs)
450 bs_[pos_] = static_cast<bool>(rhs);
454 reference &operator=(bool val)
460 operator bool() const
466 std::bitset<FlagGroup::FLAG_TYPE_MAX> &bs_;
472 * @brief 指定したフラグへのアクセスを提供するプロキシオブジェクトを取得する
474 * @param f プロキシオブジェクトを取得するフラグ
475 * @return reference 指定したフラグへのアクセスを提供するプロキシオブジェクト
477 reference operator[](FlagType f)
479 return reference(bs_, static_cast<size_t>(f));
483 /** フラグ集合を保持するstd::bitsetのインスタンス */
484 std::bitset<FLAG_TYPE_MAX> bs_;