data_flags.h 1.5 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283
  1. /*
  2. This file is part of Telegram Desktop,
  3. the official desktop application for the Telegram messaging service.
  4. For license and copyright information please follow this link:
  5. https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
  6. */
  7. #pragma once
  8. #include <rpl/event_stream.h>
  9. namespace Data {
  10. template <typename FlagsType>
  11. using FlagsUnderlying = typename FlagsType::Type;
  12. template <
  13. typename FlagsType,
  14. FlagsUnderlying<FlagsType> kEssential = FlagsUnderlying<FlagsType>(-1)>
  15. class Flags {
  16. public:
  17. using Type = FlagsType;
  18. using Enum = typename Type::Enum;
  19. struct Change {
  20. using Type = FlagsType;
  21. using Enum = typename Type::Enum;
  22. Change(Type diff, Type value)
  23. : diff(diff)
  24. , value(value) {
  25. }
  26. Type diff = 0;
  27. Type value = 0;
  28. };
  29. Flags() = default;
  30. Flags(Type value) : _value(value) {
  31. }
  32. void set(Type which) {
  33. if (auto diff = which ^ _value) {
  34. _value = which;
  35. updated(diff);
  36. }
  37. }
  38. void add(Type which) {
  39. if (auto diff = which & ~_value) {
  40. _value |= which;
  41. updated(diff);
  42. }
  43. }
  44. void remove(Type which) {
  45. if (auto diff = which & _value) {
  46. _value &= ~which;
  47. updated(diff);
  48. }
  49. }
  50. auto current() const {
  51. return _value;
  52. }
  53. auto changes() const {
  54. return _changes.events();
  55. }
  56. auto value() const {
  57. return _changes.events_starting_with({
  58. Type::from_raw(kEssential),
  59. _value });
  60. }
  61. private:
  62. void updated(Type diff) {
  63. if ((diff &= Type::from_raw(kEssential))) {
  64. _changes.fire({ diff, _value });
  65. }
  66. }
  67. Type _value = 0;
  68. rpl::event_stream<Change> _changes;
  69. };
  70. } // namespace Data