lib/ronin/chars/char_set.rb in ronin-0.1.1 vs lib/ronin/chars/char_set.rb in ronin-0.1.2

- old
+ new

@@ -19,96 +19,179 @@ # along with this program; if not, write to the Free Software # Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA #++ # +require 'set' + module Ronin module Chars - class CharSet < Array + class CharSet < SortedSet # # Creates a new CharSet object with the given _chars_. # def initialize(*chars) - format_char = lambda { |char| - if (char.kind_of?(Array) || char.kind_of?(Range)) - char.map(&format_char) - elsif char.kind_of?(Integer) - char.chr - else - char.to_s + super() + + merge_chars = lambda { |element| + if element.kind_of?(String) + element.each_byte(&merge_chars) + elsif element.kind_of?(Integer) + self << element + elsif element.kind_of?(Enumerable) + element.each(&merge_chars) end } - super(chars.map(&format_char).flatten.uniq) + merge_chars.call(chars) end + alias include_byte? include? + alias bytes to_a + alias each_byte each + alias select_bytes select + alias map_bytes map + # - # Create a new CharSet object containing the characters that match + # Returns +true+ if the character set includes the specified _char_, + # returns +false+ otherwise. + # + def include_char?(char) + char.each_byte do |b| + return include?(b) + end + end + + # + # Returns all the characters within the character set as Strings. + # + def chars + map { |b| b.chr } + end + + # + # Iterates over every character within the character set, passing + # each to the given _block_. + # + def each_char(&block) + each { |b| block.call(b.chr) } if block + end + + # + # Selects an Array of characters from the character set that match # the given _block_. # - def select(&block) - CharSet.new(super(&block)) + def select_chars(&block) + chars.select(&block) end # - # Creates a new CharSet object by passing each character to the - # specified _block_. + # Maps the characters of the character set using the given _block_. # - def map(&block) - CharSet.new(super(&block)) + def map_chars(&block) + chars.map(&block) end # + # Returns a random byte from the character set. + # + def random_byte + self.entries[rand(self.length)] + end + + # # Returns a random char from the character set. # def random_char - self[rand(self.length)] + random_byte.chr end # + # Pass a random byte to the specified _block_, _n_ times. + # + def each_random_byte(n,&block) + n.times { block.call(random_byte) } + end + + # # Pass a random character to the specified _block_, _n_ times. # def each_random_char(n,&block) - n.to_i.times { block.call(random_char) } + each_random_byte(n) { |b| block.call(b.chr) } end # # Returns an Array of the specified _length_ containing - # random characters from the character set. + # random bytes from the character set. The specified _length_ may + # be an Integer, Array or a Range of lengths. # - def random_array(length) - if length.kind_of?(Range) - return Array.new(length.sort_by { rand }.first) { random_char } + def random_bytes(length) + if (length.kind_of?(Array) || length.kind_of?(Range)) + return Array.new(length.sort_by { rand }.first) { random_byte } else - return Array.new(length.to_i) { random_char } + return Array.new(length) { random_byte } end end # + # Returns an Array of the specified _length_ containing + # random characters from the character set. The specified _length_ + # may be an Integer, Array or a Range of lengths. + # + def random_chars(length) + random_bytes(length).map { |b| b.chr } + end + + # # Returns a String of the specified _length_ containing # random characters from the character set. # def random_string(length) - random_array(length).join + random_chars(length).join end # - # Return a new CharSet that is the union of the character set and the - # specified _other_set_. + # Creates a new CharSet object containing the both the characters + # of the character set and the specified _other_set_. # def |(other_set) - CharSet.new(self,other_set) + super(CharSet.new(other_set)) end alias + | # - # Returns a new CharSet that is the intersection of the character set - # and the specified _other_set_. + # Returns +true+ if all of the bytes within the specified _string_ + # are included in the character set, returns +false+ otherwise. # - def -(other_set) - CharSet.new(super(other_set.to_a)) + # Chars.alpha =~ "hello" + # # => true + # + def =~(string) + string.each_byte do |b| + return false unless include?(b) + end + + return true + end + + # + # Inspects the character set. + # + def inspect + "#<#{self.class.name}: {" + map { |b| + case b + when (0x07..0x0d), (0x20..0x7e) + b.chr.dump + when 0x00 + # sly hack to make char-sets more friendly + # to us C programmers + '"\0"' + else + "0x%02x" % b + end + }.join(', ') + "}>" end end end end