6 * @brief フラグ集合を扱う、FlagGroupクラス
8 * @tparam FlagType 扱うフラグ集合を定義したenum class型
10 template <typename FlagType>
14 static constexpr auto FLAG_TYPE_MAX = static_cast<size_t>(FlagType::MAX);
18 * @brief フラグ集合に含まれるフラグの種類数を返す
20 * @return constexpr size_t フラグ集合に含まれるフラグの種類数
22 constexpr size_t size() const noexcept
28 * @brief FlagGroupクラスのデフォルトコンストラクタ
30 * すべてのフラグがOFFの状態のFlagGroupクラスのインスタンスを生成する
32 FlagGroup<FlagType>() = default;
35 * @brief FlagGroupクラスのコンストラクタ
37 * initializer_listで指定したフラグがON、それ以外はOFFの状態の
38 * FlagGroupクラスのインスタンスを生成する
40 * @param il ONの状態で生成するフラグを指定した initializer_list
42 FlagGroup<FlagType>(std::initializer_list<FlagType> il)
48 * @brief FlagGroupクラスのコンストラクタ
50 * 入力イテレータで指定した範囲のリストに含まれるフラグがON、
51 * それ以外のフラグがOFFの状態のFlagGroupクラスのインスタンスを生成する
53 * @tparam InputIter 入力イテレータの型
54 * @param first 範囲の開始位置を示す入力イテレータ
55 * @param last 範囲の終了位置を示す入力イテレータ
57 template <typename InputIter>
58 FlagGroup<FlagType>(InputIter first, InputIter last)
64 * @brief フラグ集合に含まれるフラグをすべてOFFにする
66 * @return FlagGroup<FlagType>& *thisを返す
68 FlagGroup<FlagType> &clear() noexcept
75 * @brief 指定したフラグを指定した値にセットする
77 * @param flag 値をセットするフラグを指定する
78 * @param val セットする値。trueならフラグをON、falseならフラグをOFFにする。
79 * 引数を省略した場合はフラグをONにする。
80 * @return FlagGroup<FlagType>& *thisを返す
82 FlagGroup<FlagType> &set(FlagType flag, bool val = true)
84 bs_.set(static_cast<size_t>(flag), val);
89 * @brief 入力イテレータで指定した範囲のリストに含まれるフラグをONにする
91 * @tparam InputIter 入力イテレータの型
92 * @param first 範囲の開始位置を示す入力イテレータ
93 * @param last 範囲の終了位置を示す入力イテレータ
94 * @return FlagGroup<FlagType>& *thisを返す
96 template <typename InputIter>
97 FlagGroup<FlagType> &set(InputIter first, InputIter last)
99 static_assert(std::is_same<typename std::iterator_traits<InputIter>::value_type, FlagType>::value, "Iterator value type is invalid");
101 for (; first != last; ++first) {
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 for (; first != last; ++first) {
164 * @brief 指定したFlagGroupのインスンタンスのONになっているフラグをOFFにする
166 * @param rhs OFFにするフラグがONになっているFlagGroupのインスタンス
167 * @return FlagGroup<FlagType>& *thisを返す
169 FlagGroup<FlagType> &reset(const FlagGroup<FlagType> &rhs)
176 * @brief 指定したinitializer_listに含まれるフラグをOFFにする
178 * @param list OFFにするフラグを列挙したinitializer_list
179 * @return FlagGroup<FlagType>& *thisを返す
181 FlagGroup<FlagType> &reset(std::initializer_list<FlagType> list)
183 return reset(std::begin(list), std::end(list));
187 * @brief 指定したフラグがONかOFFか調べる
189 * @param f 調べるフラグを指定する
190 * @return bool 指定したフラグがONならtrue、OFFならfalse
192 bool has(FlagType f) const
194 return bs_.test(static_cast<size_t>(f));
198 * @brief 指定したフラグがOFFかONか調べる
200 * @param f 調べるフラグを指定する
201 * @return bool 指定したフラグがOFFならtrue、ONならfalse
203 bool has_not(FlagType f) const
209 * @brief フラグ集合のいずれかのフラグがONかどうかを調べる
211 * @return bool フラグ集合のいずれかのフラグがONならtrue
212 * フラグ集合のすべてのフラグがOFFならfalse
214 bool any() const noexcept
220 * @brief フラグ集合のすべてのフラグがOFFかどうかを調べる
222 * @return bool フラグ集合のすべてのフラグがOFFならtrue
223 * フラグ集合のいずれかのフラグがONならfalse
225 bool none() const noexcept
231 * @brief 入力イテレータで指定した範囲のリストに含まれるフラグがすべてONかどうかを調べる
233 * @tparam InputIter 入力イテレータの型
234 * @param first 範囲の開始位置を示す入力イテレータ
235 * @param last 範囲の終了位置を示す入力イテレータ
236 * @return bool すべてのフラグがONであればtrue、そうでなければfalse
238 template <typename InputIter>
239 bool has_all_of(InputIter first, InputIter last) const
241 static_assert(std::is_same<typename std::iterator_traits<InputIter>::value_type, FlagType>::value, "Iterator value type is invalid");
243 for (; first != last; ++first) {
244 if (has_not(*first)) {
253 * @brief 指定したinitializer_listに含まれるフラグがすべてONかどうかを調べる
255 * @param list 調べるフラグを列挙したinitializer_list
256 * @return bool すべてのフラグがONであればtrue、そうでなければfalse
258 bool has_all_of(std::initializer_list<FlagType> list) const
260 return has_all_of(std::begin(list), std::end(list));
264 * @brief 引数で指定したFlagGroupのインスンタンスのONになっているフラグがすべてONかどうかを調べる
266 * @param rhs FlagGroupのインスタンス
267 * @return bool すべてのフラグがONであればtrue、そうでなければfalse
269 bool has_all_of(const FlagGroup<FlagType> &rhs) const
271 return (bs_ & rhs.bs_) == rhs.bs_;
275 * @brief 入力イテレータで指定した範囲のリストに含まれるフラグのいずれかがONかどうかを調べる
277 * @tparam InputIter 入力イテレータの型
278 * @param first 範囲の開始位置を示す入力イテレータ
279 * @param last 範囲の終了位置を示す入力イテレータ
280 * @return bool いずれかのフラグがONであればtrue、そうでなければfalse
282 template <typename InputIter>
283 bool has_any_of(InputIter first, InputIter last) const
285 static_assert(std::is_same<typename std::iterator_traits<InputIter>::value_type, FlagType>::value, "Iterator value type is invalid");
287 for (; first != last; ++first) {
297 * @brief 指定したinitializer_listに含まれるフラグのいずれかがONかどうかを調べる
299 * @param list 調べるフラグを列挙したinitializer_list
300 * @return bool いずれかのフラグがONであればtrue、そうでなければfalse
302 bool has_any_of(std::initializer_list<FlagType> list) const
304 return has_any_of(std::begin(list), std::end(list));
308 * @brief 引数で指定したFlagGroupのインスンタンスのONになっているフラグのいずれかがONかどうかを調べる
310 * @param rhs FlagGroupのインスタンス
311 * @return bool いずれかのフラグがONであればtrue、そうでなければfalse
313 bool has_any_of(const FlagGroup<FlagType> &rhs) const
315 return (bs_ & rhs.bs_) != 0;
319 * @brief 入力イテレータで指定した範囲のリストに含まれるフラグがすべてOFFかどうかを調べる
321 * @tparam InputIter 入力イテレータの型
322 * @param first 範囲の開始位置を示す入力イテレータ
323 * @param last 範囲の終了位置を示す入力イテレータ
324 * @return bool すべてのフラグがOFFであればtrue、そうでなければfalse
326 template <typename InputIter>
327 bool has_none_of(InputIter first, InputIter last) const
329 static_assert(std::is_same<typename std::iterator_traits<InputIter>::value_type, FlagType>::value, "Iterator value type is invalid");
331 return !has_any_of(first, last);
335 * @brief 指定したinitializer_listに含まれるフラグがすべてOFFかどうかを調べる
337 * @param list 調べるフラグを列挙したinitializer_list
338 * @return bool すべてのフラグがOFFであればtrue、そうでなければfalse
340 bool has_none_of(std::initializer_list<FlagType> list) const
342 return !has_any_of(list);
346 * @brief 引数で指定したFlagGroupのインスンタンスのONになっているフラグがすべてOFFかどうかを調べる
348 * @param rhs FlagGroupのインスタンス
349 * @return bool すべてのフラグがOFFであればtrue、そうでなければfalse
351 bool has_none_of(const FlagGroup<FlagType> &rhs) const
353 return !has_any_of(rhs);
357 * @brief フラグ集合のONになっているフラグの数を返す
359 * @return size_t ONになっているフラグの数
361 size_t count() const noexcept
367 * @brief フラグ集合の状態を0と1で表した文字列を返す
369 * フラグ集合の上位番号から順に、フラグがONなら1、OFFなら0で表した文字列を返す。
370 * 例: 5つのフラグ集合で、0:ON、1:OFF、2:OFF、3:ON、4:OFFの場合、"01001"
372 * @return std::string フラグ集合の状態を表した文字列
374 std::string str() const
376 return bs_.to_string();
380 * @brief セーブファイルからフラグ集合を読み出す
382 * @param fg 読み出したフラグ集合を格納するFlagGroupインスタンスの参照
383 * @param rd_byte_func セーブファイルから1バイトデータを読み出す関数(rd_byte)へのポインタ
385 template <typename Func>
386 friend void rd_FlagGroup(FlagGroup<FlagType> &fg, Func rd_byte_func)
388 uint8_t tmp_l, tmp_h;
389 rd_byte_func(&tmp_l);
390 rd_byte_func(&tmp_h);
391 const auto fg_size = static_cast<uint16_t>((tmp_h << 8) | tmp_l);
393 for (int i = 0; i < fg_size; i++) {
395 rd_byte_func(&flag_byte);
396 std::bitset<8> flag_bits(flag_byte);
397 for (int j = 0; j < 8; j++) {
398 const size_t pos = i * 8 + j;
399 if (pos < fg.bs_.size()) {
400 fg.bs_[pos] = flag_bits[j];
407 * @brief セーブファイルにフラグ集合を書き込む
409 * @param fg 書き込むフラグ集合を保持したFlagGroupインスタンスの参照
410 * @param wr_byte_func セーブファイルに1バイトデータを書き込む関数(wr_byte)へのポインタ
412 template <typename Func>
413 friend void wr_FlagGroup(const FlagGroup<FlagType> &fg, Func wr_byte_func)
415 const auto fg_size = static_cast<uint16_t>((fg.bs_.size() + 7) / 8);
416 wr_byte_func(fg_size & 0xff);
417 wr_byte_func((fg_size >> 8) & 0xff);
419 for (int i = 0; i < fg_size; i++) {
420 std::bitset<8> flag_bits;
421 for (int j = 0; j < 8; j++) {
422 const size_t pos = i * 8 + j;
423 if (pos < fg.bs_.size()) {
424 flag_bits[j] = fg.bs_[pos];
427 wr_byte_func(flag_bits.to_ulong() & 0xff);
432 * @brief 文字列からフラグへのマップを指定した検索キーで検索し、
433 * 見つかった場合はフラグ集合に該当するフラグをセットする
435 * @tparam Map std::map<string_view, FlagType> もしくは std::unordered_map<string_view, FlagType>
436 * @param fg フラグをセットするフラグ集合
437 * @param dict 文字列からフラグへのマップ
438 * @param what マップの検索キー
439 * @return bool 検索キーでフラグが見つかり、フラグをセットした場合 true
442 template <typename Map>
443 static bool grab_one_flag(FlagGroup<FlagType> &fg, const Map &dict, std::string_view what)
445 auto it = dict.find(what);
446 if (it == dict.end())
455 * @brief 指定したフラグ位置へのアクセスを提供するプロキシクラス
459 reference(std::bitset<FlagGroup::FLAG_TYPE_MAX> &flags, size_t pos)
465 reference &operator=(const reference &rhs)
467 bs_[pos_] = static_cast<bool>(rhs);
471 reference &operator=(bool val)
477 operator bool() const
483 std::bitset<FlagGroup::FLAG_TYPE_MAX> &bs_;
489 * @brief 指定したフラグへのアクセスを提供するプロキシオブジェクトを取得する
491 * @param f プロキシオブジェクトを取得するフラグ
492 * @return reference 指定したフラグへのアクセスを提供するプロキシオブジェクト
494 reference operator[](FlagType f)
496 return reference(bs_, static_cast<size_t>(f));
500 /** フラグ集合を保持するstd::bitsetのインスタンス */
501 std::bitset<FLAG_TYPE_MAX> bs_;