Guest User

Untitled

a guest
Feb 21st, 2018
87
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
text 3.46 KB | None | 0 0
  1. class FlagSet
  2. class Flags
  3. class <<self
  4. # frozen flags
  5. attr_reader :flags
  6. # the amount of possible states
  7. attr_reader :states
  8.  
  9. # If this flagset includes certain flag
  10. def include?(flag)
  11. @position.has_key?(flag)
  12. end
  13.  
  14. # Get the Position of a flag
  15. def position(flag)
  16. @position[flag]
  17. end
  18.  
  19. # Convert an integer to this kind of FlagSet
  20. def from(integer)
  21. raise ArgumentError, "Invalid State, maximum is #{states-1}" unless integer < states
  22. new(*@flags.select { |flag| integer[position(flag)] == 1 })
  23. end
  24. alias from_integer from
  25. end
  26.  
  27. def initialize(*flags)
  28. flags = flags.map { |flag| flag.to_sym }
  29. @value = flags.inject(0) { |sum, flag|
  30. raise ArgumentError, "Invalid flag #{flag}" unless position = self.class.position(flag)
  31. sum + 2**position
  32. }
  33. end
  34.  
  35. # Flagwise AND (returns a FlagSet with all Flags set in both)
  36. def &(other)
  37. self.class.from(other.to_i & self.to_i)
  38. end
  39.  
  40. # Flagwise OR (returns a FlagSet with all Flags set in either)
  41. def |(other)
  42. self.class.from(other.to_i | self.to_i)
  43. end
  44.  
  45. # Flagwise exclusive OR (returns a FlagSet with all Flags set in only one of either)
  46. def ^(other)
  47. self.class.from(other.to_i ^ self.to_i)
  48. end
  49.  
  50. # An Integer-representation of the FlagSet
  51. def to_i
  52. @value
  53. end
  54.  
  55. # The flags set in this FlagSet
  56. def flags
  57. flags = []
  58. self.class.flags.each_with_index { |flag, index| flags << flag if @value[index] == 1 }
  59. flags
  60. end
  61. end
  62.  
  63. # Example:
  64. # MyFlags = FlagSet.new(:a, :b, :c)
  65. # x = MyFlags.new(:a, :b)
  66. # x.a? # => true
  67. # x.b? # => true
  68. # x.c? # => false
  69. # x.c!
  70. # x.a!(false)
  71. # x.a? # => false
  72. # x.b? # => true
  73. # x.c? # => true
  74. def self.new(*flags)
  75. str_flags = flags.map { |flag| flag.to_s }
  76. sym_flags = []
  77. position = {}
  78. str_flags.each_with_index { |flag, index|
  79. raise ArgumentError, "Invalid flag #{flag}" unless flag =~ /\A[A-Za-z_][A-Za-z0-9_]*\z/ && !Flags.instance_methods.include?(flag)
  80. sym_flag = flag.to_sym
  81. position[sym_flag] = index
  82. sym_flags << sym_flag
  83. }
  84. flagset = Class.new(Flags)
  85. flagset.instance_variable_set("@flags", sym_flags)
  86. flagset.instance_variable_get("@flags").freeze
  87. flagset.instance_variable_set("@position", position)
  88. flagset.instance_variable_set("@states", 2**(str_flags.length))
  89. str_flags.each_with_index { |flag, position|
  90. flagset.class_eval("def #{flag}?; @value[#{position}] == 1; end")
  91. flagset.class_eval("def #{flag}!(set=true); if set then @value |= #{2**position} else @value &= #{2**position} end; end")
  92. }
  93. flagset
  94. end
  95. end
  96.  
  97. if __FILE__ == $0 then
  98. Permission = FlagSet.new(
  99. :owner_execute,
  100. :owner_read,
  101. :owner_write,
  102. :group_execute,
  103. :group_read,
  104. :group_write,
  105. :world_execute,
  106. :world_read,
  107. :world_write
  108. )
  109.  
  110. p ["states", Permission.states] # => true
  111. p x = Permission.new(:owner_execute)
  112. p (x.methods - Object.methods).sort
  113. p ["owner_execute?", x.owner_execute?] # => true
  114. p ["world_read?", x.world_read?] # => false
  115. p ["world_read!", x.world_read!]
  116. p ["world_read?", x.world_read?] # => true
  117. p ["x.to_i", i = x.to_i] # => 1
  118. y = Permission.from_integer(i)
  119. p ["y", y]
  120. p ["y.flags", y.flags] # => [:owner_execute, :world_read]
  121. z = Permission.new(:group_write, :owner_execute)
  122. p ["(z | y).flags", (z | y).flags]
  123. p ["(z & y).flags", (z & y).flags]
  124. p ["(z ^ y).flags", (z ^ y).flags]
  125. end
Add Comment
Please, Sign In to add comment