Guest User

Untitled

a guest
Feb 21st, 2018
76
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
text 3.52 KB | None | 0 0
  1. class FlagSet
  2. class <<self
  3. # frozen flags
  4. attr_reader :flags
  5. # the amount of possible states
  6. attr_reader :states
  7.  
  8. # If this flagset includes certain flag
  9. def include?(flag)
  10. @position.has_key?(flag)
  11. end
  12.  
  13. # Get the Position of a flag
  14. def position(flag)
  15. @position[flag]
  16. end
  17.  
  18. # Convert an integer to this kind of FlagSet
  19. def from(integer)
  20. raise ArgumentError, "Invalid State, maximum is #{states-1}" unless integer < states
  21. new(*@flags.select { |flag| integer[position(flag)] == 1 })
  22. end
  23. alias from_integer from
  24.  
  25.  
  26. # Example:
  27. # MyFlags = FlagSet.new(:a, :b, :c)
  28. # x = MyFlags.new(:a, :b)
  29. # x.a? # => true
  30. # x.b? # => true
  31. # x.c? # => false
  32. # x.c!
  33. # x.a!(false)
  34. # x.a? # => false
  35. # x.b? # => true
  36. # x.c? # => true
  37. def new(*flags)
  38. str_flags = flags.map { |flag| flag.to_s }
  39. sym_flags = []
  40. position = {}
  41. str_flags.each_with_index { |flag, index|
  42. raise ArgumentError, "Invalid flag #{flag}" unless flag =~ /\A[A-Za-z_][A-Za-z0-9_]*\z/ && !self.instance_methods.include?(flag)
  43. sym_flag = flag.to_sym
  44. position[sym_flag] = index
  45. sym_flags << sym_flag
  46. }
  47. flagset = Class.new(FlagSet)
  48. flagset.instance_variable_set("@flags", sym_flags)
  49. flagset.instance_variable_get("@flags").freeze
  50. flagset.instance_variable_set("@position", position)
  51. flagset.instance_variable_set("@states", 2**(str_flags.length))
  52. str_flags.each_with_index { |flag, position|
  53. flagset.class_eval("def #{flag}?; @value[#{position}] == 1; end")
  54. flagset.class_eval("def #{flag}!(set=true); if set then @value |= #{2**position} else @value &= #{2**position} end; end")
  55. }
  56. class <<flagset; define_method(:new, (class <<Object; instance_method(:new); end)); end # restore new-method
  57. flagset
  58. end
  59. end
  60.  
  61. def initialize(*flags)
  62. flags = flags.map { |flag| flag.to_sym }
  63. @value = flags.inject(0) { |sum, flag|
  64. raise ArgumentError, "Invalid flag #{flag}" unless position = self.class.position(flag)
  65. sum + 2**position
  66. }
  67. end
  68.  
  69. # Flagwise AND (returns a FlagSet with all Flags set in both)
  70. def &(other)
  71. self.class.from(other.to_i & self.to_i)
  72. end
  73.  
  74. # Flagwise OR (returns a FlagSet with all Flags set in either)
  75. def |(other)
  76. self.class.from(other.to_i | self.to_i)
  77. end
  78.  
  79. # Flagwise exclusive OR (returns a FlagSet with all Flags set in only one of either)
  80. def ^(other)
  81. self.class.from(other.to_i ^ self.to_i)
  82. end
  83.  
  84. # An Integer-representation of the FlagSet
  85. def to_i
  86. @value
  87. end
  88.  
  89. # The flags set in this FlagSet
  90. def flags
  91. flags = []
  92. self.class.flags.each_with_index { |flag, index| flags << flag if @value[index] == 1 }
  93. flags
  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