class GxG::ByteArray
Public Class Methods
[](*args)
click to toggle source
# File lib/gxg/gxg_elements.rb, line 538 def self.[](*args) GxG::ByteArray.new(*args) end
new(*args,&block)
click to toggle source
instance methods:
Calls superclass method
# File lib/gxg/gxg_elements.rb, line 571 def initialize(*args,&block) # Integer(how_many), <Acceptable-data-type>, <Max-size>, <Pad-value>, <Outer-value> # --OR-- # Integer(how_many), <Max-size>, <Pad-value>, <Outer-value> &block @data = "" @data.force_encoding(Encoding::ASCII_8BIT) # memory_limits = GxG::SYSTEM.memory_limits() @max_size = nil @pad_value = 0 @outer = nil # *should* create a 'self' to call upon. super() # if args.size > 0 if block.respond_to?(:call) if args[0].is_a?(Numeric) args[0] = args[0].to_i if args[0] >= 0 if args[0] > memory_limits[:process].first args[0] = memory_limits[:process].first end if args[1].is_a?(Numeric) self.maxsize = args[1].to_i end if args[2].is_a?(Numeric) self.padvalue = args[1].to_i end if args[3].is_a?(Numeric) self.outervalue = args[1].to_i end # (0..(args[0] - 1)).to_enum.each do |index| raw_data_array = [(block.call(index))].flatten raw_data_array.to_enum.each do |raw_data| # raw_data = (self.filter_data(raw_data) || "") # if raw_data.bytesize > 0 if (args[0] * raw_data.bytesize) > memory_limits[:process].first # Attempts to project whether or not maximum memory limits will be exceeded. # LATER: ByteArray.new: Might get false positives on variable return data from block (re-think this) raise NoMemoryError.new("This operation will exceed available per-process memory limits") end @data << raw_data end end # end # if @max_size if @data.bytesize > @max_size @max_size = @data.bytesize end end # end end else # if args[0].is_a?(Numeric) how_many = args[0].to_i if args[1] raw_data_array = [(args[1])].flatten else raw_data_array = [(@pad_value.to_i.chr)] end if args[2].is_a?(Numeric) self.maxsize = args[2].to_i end if args[3].is_a?(Numeric) self.padvalue = args[3].to_i end if args[4].is_a?(Numeric) self.outervalue = args[4].to_i end else how_many = 1 raw_data_array = [(args[0])].flatten if args[1].is_a?(Numeric) self.maxsize = args[1].to_i end if args[2].is_a?(Numeric) self.padvalue = args[2].to_i end if args[3].is_a?(Numeric) self.outervalue = args[3].to_i end end # new_data = "" new_data.force_encoding(Encoding::ASCII_8BIT) raw_data_array.to_enum.each do |raw_data| new_data << (self.filter_data(raw_data) || "") end if new_data.bytesize > 0 if (how_many * new_data.bytesize) > memory_limits[:process].first raise NoMemoryError.new("This operation will exceed available per-process memory limits") end how_many.times do @data << new_data end end # if @max_size if @data.bytesize > @max_size @max_size = @data.bytesize end end # end # end self end
process(the_array=GxG::ByteArray.new,&block)
click to toggle source
# File lib/gxg/gxg_elements.rb, line 542 def self.process(the_array=GxG::ByteArray.new,&block) new_array = GxG::ByteArray.new if block.respond_to?(:call) if the_array.is_any?(::Array, ::Hash, ::GxG::ByteArray, ::Set, ::Struct) new_array = the_array.process(&block) else raise ArgumentError, "you must pass an Array, a ByteArray, or a Hash" end end new_array end
search(the_array=GxG::ByteArray.new,&block)
click to toggle source
# File lib/gxg/gxg_elements.rb, line 554 def self.search(the_array=GxG::ByteArray.new,&block) new_array = GxG::ByteArray.new if block.respond_to?(:call) if the_array.is_any?(::Array, ::Hash, ::GxG::ByteArray, ::Set, ::Struct) new_array = the_array.search(&block) else raise ArgumentError, "you must pass an Array, a ByteArray, or a Hash" end end new_array end
try_convert(*args)
click to toggle source
# File lib/gxg/gxg_elements.rb, line 530 def self.try_convert(*args) begin GxG::ByteArray.new(1,[(args)]) rescue Exception nil end end
Public Instance Methods
&(*args)
click to toggle source
# File lib/gxg/gxg_elements.rb, line 994 def &(*args) result = GxG::ByteArray.new if args.size > 0 other = GxG::ByteArray::try_convert(args) if other result_scrap = "" result_scrap.force_encoding(Encoding::ASCII_8BIT) self.each do |the_byte| if other.include?(the_byte) result_scrap << the_byte.chr end end result = GxG::ByteArray.new(result_scrap) end end result end
*(*args)
click to toggle source
# File lib/gxg/gxg_elements.rb, line 1012 def *(*args) result = GxG::ByteArray.new if self.size > 0 if args.size > 0 if args[0].is_a?(::String) result = self.join(args[0]) else if args[0].is_a?(Numeric) scrap_size = ((args[0].to_f % args[0].to_i.to_f) * self.size.to_f).to_i args[0] = args[0].to_i if (args[0] * self.size) <= GxG::SYSTEM.memory_limits()[:process].first args[0].times do result << self.data().clone end if scrap_size > 0 result << self.data()[0..(scrap_size)] end else raise NoMemoryError.new("This operation will exceed per-process memory limits") end else raise ArgumentError.new("a String or Numeric is required, you provied #{args[0].inspect}") end end else raise TypeError.new("Can't convert nil to ByteArray") end end result end
+(*args)
click to toggle source
# File lib/gxg/gxg_elements.rb, line 1043 def +(*args) result = GxG::ByteArray.new if args.size > 0 other = GxG::ByteArray::try_convert(args) if other if other.size > 0 result = GxG::ByteArray.new(1,[(self.data().clone),(other.data())]) end end else raise TypeError.new("Can't convert nil to ByteArray") end result end
-(*args)
click to toggle source
# File lib/gxg/gxg_elements.rb, line 1058 def -(*args) result = GxG::ByteArray.new if args.size > 0 scrap = GxG::ByteArray::try_convert(args) if scrap result_scrap = "" result_scrap.force_encoding(Encoding::ASCII_8BIT) self.each do |the_byte| unless scrap.include?(the_byte) result_scrap << the_byte.chr end end result = GxG::ByteArray.new(result_scrap) end end result end
<<(*args)
click to toggle source
# File lib/gxg/gxg_elements.rb, line 1076 def <<(*args) if args.size > 0 value = GxG::ByteArray::try_convert(args) if value if @max_size if (@data.bytesize + value.size) > @max_size raise RangeError.new("Operation exceeds #{@max_size} limit. You might need to adjust maxsize.") end end @data << value.data() end end self end
<=>(*args)
click to toggle source
# File lib/gxg/gxg_elements.rb, line 1091 def <=>(*args) result = 1 if args.size > 0 if args[0].is_a?(::GxG::ByteArray) result = (self.data() <=> args[0].data()) else # Allows sorting against std. Array or String that *would* sort normal if it were a ByteArray (byte comparison) other = GxG::ByteArray::try_convert(args) if other result = (self.data() <=> other.data()) end end end result end
==(*args)
click to toggle source
# File lib/gxg/gxg_elements.rb, line 1107 def ==(*args) result = false if args.size > 0 if args[0].is_a?(::GxG::ByteArray) result = (self.data() == args[0].data()) else # kinda cool, but might be a bridge too far for strict equivalence. # other = GxG::ByteArray::try_convert(args) # if other # result = (self.data() == other.data()) #end end end result end
[](indexer=0, length=nil)
click to toggle source
# File lib/gxg/gxg_elements.rb, line 886 def [](indexer=0, length=nil) self.slice(indexer,length) end
[]=(indexer=0, length=nil, value=nil)
click to toggle source
# File lib/gxg/gxg_elements.rb, line 890 def []=(indexer=0, length=nil, value=nil) # if length unless value value = length length = nil end end value = self.filter_data(value) error = nil result = nil # if value if value.bytesize > 0 # the_range = self.filter_parameters(indexer,length) # unless the_range if length error = ArgumentError.new("#{indexer.inspect},#{length.inspect} could not be fashioned into a valid Indexer") else error = ArgumentError.new("#{indexer.inspect} could not be fashioned into a valid Indexer") end end if error raise error end # check overall compliance with maxsize if @max_size if (the_range.count > @max_size || the_range.first > (@max_size - 1) || the_range.last > (@max_size - 1)) error = IndexError.new("Index exceeds #{@max_size} limit. You might need to adjust maxsize.") end if (the_range.first + (value.bytesize - 1)) > (@max_size - 1) error = RangeError.new("Data size at specified Index exceeds #{@max_size} limit. You might need to adjust maxsize.") end # if indexer.is_a?(Integer) if length # replace operation if (the_range.first + (the_range.count - 1)) > (@max_size - 1) error = RangeError.new("Range exceeds #{@max_size} limit. You might need to adjust maxsize.") else if the_range.count < value.bytesize and (the_range.first + (the_range.count - 1) + ((value.bytesize - 1) - (the_range.count - 1))) > (@max_size - 1) error = RangeError.new("Value size exceeds #{@max_size} limit. You might need to adjust maxsize.") end end else # insert operation if (@data.size - 1 + value.bytesize) > @max_size error = RangeError.new("Operation exceeds #{@max_size} limit. You might need to adjust maxsize.") end if (the_range.first + (value.bytesize - 1)) > (@max_size - 1) error = RangeError.new("Value size exceeds #{@max_size} limit. You might need to adjust maxsize.") end end else if the_range.count > @max_size error = RangeError.new("Range exceeds #{@max_size} limit. You might need to adjust maxsize.") else if the_range.count < value.bytesize and (the_range.first + (the_range.count - 1) + ((value.bytesize - 1) - (the_range.count - 1))) > (@max_size - 1) error = RangeError.new("Value size exceeds #{@max_size} limit. You might need to adjust maxsize.") end end end if error raise error end end # if the_range.first > (@data.bytesize - 1) (the_range.first - (@data.bytesize - 1)).times do @data << @pad_value.chr end end # if length @data[(the_range.first),(the_range.count)] = value else if indexer.is_a?(Numeric) @data[(the_range.first)] = value else @data[(the_range)] = value end end # end result = GxG::ByteArray.new(value) end result end
at(*args)
click to toggle source
# File lib/gxg/gxg_elements.rb, line 1123 def at(*args) if args[0].is_a?(Float) args[0] = args[0].to_i end if args[0].is_a?(Integer) self[(args[0])] else raise TypeError.new("Expected Integer or Float. You provided #{args[0].class}") end end
clear()
click to toggle source
# File lib/gxg/gxg_elements.rb, line 1134 def clear() @data.clear self end
clone()
click to toggle source
# File lib/gxg/gxg_elements.rb, line 882 def clone() initialize_dup() end
collect(&block)
click to toggle source
# File lib/gxg/gxg_elements.rb, line 1139 def collect(&block) result = GxG::ByteArray.new if block.respond_to?(:call) result_scrap = "" result_scrap.force_encoding(Encoding::ASCII_8BIT) self.each do |the_byte| result_scrap << self.filter_data(block.call(the_byte)) end result = GxG::ByteArray.new(result_scrap) else result = self.to_enum(:each) end result end
Also aliased as: map
collect!(&block)
click to toggle source
# File lib/gxg/gxg_elements.rb, line 1154 def collect!(&block) if block.respond_to?(:call) self.replace(self.collect(&block).data()) self else self.to_enum(:each) end end
Also aliased as: map!
combination(*args,&block)
click to toggle source
# File lib/gxg/gxg_elements.rb, line 1163 def combination(*args,&block) # TODO: port c code to ruby (true-enumeration-as-bytearray support) enumerator = @data.to_enum(:bytes).to_a.to_enum(:combination,*args) if block.respond_to?(:call) enumerator.each do |the_combination| block.call(GxG::ByteArray.new(the_combination)) end self else # Note: this form does not put bytearrays of each combination into the block, just arrays (please fix) GxG::Enumerator.new(enumerator) end end
compact()
click to toggle source
# File lib/gxg/gxg_elements.rb, line 1190 def compact() self end
Also aliased as: compact!
concat(*args)
click to toggle source
# File lib/gxg/gxg_elements.rb, line 1194 def concat(*args) result = self if args.size > 0 other = GxG::ByteArray::try_convert(args) if other result = (self + other) else raise Exception.new("Could not convert #{args.inspect} to ByteArray") end end result end
count(match_value=nil,&block)
click to toggle source
# File lib/gxg/gxg_elements.rb, line 1207 def count(match_value=nil,&block) result = 0 if match_value.is_a?(Numeric) self.each do |the_byte| if the_byte == match_value.to_i result += 1 end end else if block.respond_to?(:call) self.each do |the_byte| if block.call(the_byte) == true result += 1 end end else result = @data.bytesize end end result end
cycle(iterations=nil,&block)
click to toggle source
# File lib/gxg/gxg_elements.rb, line 1229 def cycle(iterations=nil,&block) if @data.bytesize > 0 unless iterations.to_i < 0 if block.respond_to?(:call) if iterations iterations.to_i.times do self.each do |the_byte| block.call(the_byte) end end nil else while true do self.each do |the_byte| block.call(the_byte) end end end else @data.to_enum(:bytes).to_a.to_enum(:cycle,iterations) end end end end
data()
click to toggle source
# File lib/gxg/gxg_elements.rb, line 566 def data() @data end
dclone()
click to toggle source
# File lib/gxg/gxg_elements.rb, line 860 def dclone() result = GxG::ByteArray.new(@data.clone) result.padvalue = (self.padvalue()) result.maxsize = (self.maxsize()) result.outervalue = (self.outervalue()) result end
delete(*args,&block)
click to toggle source
# File lib/gxg/gxg_elements.rb, line 1254 def delete(*args,&block) result = nil if args[0].is_a?(Numeric) comparitor = self.filter_data(args[0].to_i) if comparitor.bytesize > 1 comparitor = comparitor[0] end scrap = @data.delete(comparitor) if scrap == @data if block.respond_to?(:call) result = block.call() end else @data.replace(scrap) result = args[0] end end result end
delete_at(*args)
click to toggle source
# File lib/gxg/gxg_elements.rb, line 1274 def delete_at(*args) result = nil if args.size > 0 the_range = self.filter_parameters(args) if the_range.last < self.size result = @data.slice!(the_range) end end result end
delete_if(&block)
click to toggle source
# File lib/gxg/gxg_elements.rb, line 1285 def delete_if(&block) self.reject!(&block) end
drop(length)
click to toggle source
# File lib/gxg/gxg_elements.rb, line 1289 def drop(length) self.slice((length.to_i - 1)..-1) end
drop_while(&block)
click to toggle source
# File lib/gxg/gxg_elements.rb, line 1293 def drop_while(&block) accumulator = GxG::ByteArray.new if block.respond_to?(:call) self.each do |the_byte| result = block.call(the_byte) unless result accumulator << the_byte end end accumulator else # TODO: 5xMem efficiency fix for various engine run conditions GxG::Enumeratior.new(@data.to_enum(:bytes).to_a.to_enum(:drop_while)) end end
each(&block)
click to toggle source
TODO: GxG::ByteArray.each_index/each_with_index: improve memory efficiency and speed significantly (!)
# File lib/gxg/gxg_elements.rb, line 1311 def each(&block) if block.respond_to?(:call) if @data.bytesize > 0 @data.to_enum(:bytes).each {|the_byte| block.call(the_byte)} end self else self.to_enum(:each) end end
each_index(&block)
click to toggle source
# File lib/gxg/gxg_elements.rb, line 1322 def each_index(&block) if block.respond_to?(:call) if @data.bytesize > 0 (0..(@data.bytesize - 1)).to_enum.each {|index| block.call(index)} end self else self.to_enum(:each_index) end end
each_with_index(offset=0,&block)
click to toggle source
# File lib/gxg/gxg_elements.rb, line 1333 def each_with_index(offset=0,&block) if block.respond_to?(:call) if @data.bytesize > 0 # bulky, but required to support self.reject!, etc : @data.to_enum(:bytes).with_index(offset).each {|value,index| block.call(value,index)} #old : (0..(@data.bytesize - 1)).to_enum.each {|index| block.call(@data[(index)].ord,index)} end self else self.to_enum(:each_with_index,offset) end end
empty?()
click to toggle source
# File lib/gxg/gxg_elements.rb, line 1346 def empty?() @data.bytesize == 0 end
eql?(*args)
click to toggle source
# File lib/gxg/gxg_elements.rb, line 1350 def eql?(*args) if args.size > 0 self == args[0] else false end end
fetch(*args,&block)
click to toggle source
# File lib/gxg/gxg_elements.rb, line 1358 def fetch(*args,&block) #fetch(index) → obj click to toggle source #fetch(index, default ) → obj #fetch(index) {|index| block } → obj # #Tries to return the element at position index. If the index lies outside the array, the first form throws an IndexError exception, # the second form returns default, and the third form returns the value of invoking the block, passing in the index. # Negative values of index count from the end of the array. # LATER: ByteArray.fetch: check how to incorporate 'padded-edges' feature if args.size > 0 if args[0].is_a?(Numeric) args[0] = self.filter_parameters(args[0].to_i).first if args[0] >= self.size if args[1] if block.respond_to?(:call) block.call(args[0]) else args[1] end else raise IndexError.new("Index specified lies outside the ByteArray") end else self.at(args[0]) end end end end
fill(*args,&block)
click to toggle source
# File lib/gxg/gxg_elements.rb, line 1387 def fill(*args,&block) #fill(obj) → ary click to toggle source #fill(obj, start [, length]) → ary #fill(obj, range ) → ary #fill {|index| block } → ary #fill(start [, length] ) {|index| block } → ary #fill(range) {|index| block } → ary # #The first three forms set the selected elements of self (which may be the entire array) to obj. A start of nil is equivalent to zero. #A length of nil is equivalent to self.length. The last three forms fill the array with the value of the block. #The block is passed the absolute index of each element to be filled. Negative values of start count from the end of the array. #a = [ "a", "b", "c", "d" ] #a.fill("x") #=> ["x", "x", "x", "x"] #a.fill("z", 2, 2) #=> ["x", "x", "z", "z"] #a.fill("y", 0..1) #=> ["y", "y", "z", "z"] #a.fill {|i| i*i} #=> [0, 1, 4, 9] #a.fill(-2) {|i| i*i*i} #=> [0, 1, 8, 27] # Note: if ByteArray is empty, it will be filled to @max_size, otherwise only the used portion or specified range. result = nil result_scrap = "" result_scrap.force_encoding(Encoding::ASCII_8BIT) # if block.respond_to?(:call) if args.size > 0 if args[0].is_a?(Numeric) args[0] = args[0].to_i if args[0] < 0 if args[1].is_a?(Numeric) if args[1].to_i > 0 args = [((@data.bytesize + args[0])..(@data.bytesize + args[0] + (args[1].to_i - 1)))] else raise ArgumentError.new("length specified should be a positive Integer for Float") end else args = [((@data.bytesize + args[0])..(@data.bytesize - 1))] end end end fillrange = self.filter_parameters(*args) else fillrange = (0..((@max_size || @data.bytesize) - 1)) end (0..(@data.bytesize - 1)).to_enum.each do |index| if fillrange.include?(index) raw_value = self.filter_data(block.call(index)) if raw_value.size > 0 # Allow only single byte results to merge into fill # since the concept is 'per-item' which in this case is a single byte only. result_scrap << raw_value[0] else result_scrap << @pad_value.chr end else result_scrap << @data[(index)] end end else if args.size > 0 value = nil case args.size when 1 fillrange = (0..((@max_size || @data.bytesize) - 1)) value = self.filter_data(args[0]) when 2 fillrange = self.filter_parameters(args[1]) value = self.filter_data(args[0]) when 3 fillrange = self.filter_parameters(args[1],args[2]) value = self.filter_data(args[0]) else fillrange = self.filter_parameters(args[1],args[2]) value = self.filter_data(args[0]) end value = (value || @pad_value.chr) # (0..(@data.bytesize - 1)).to_enum.each do |index| if fillrange.include?(index) result_scrap << value else result_scrap << @data[(index)] end end else raise ArgumentError.new("wrong number of arguments (0 for 1..3)") end end if result_scrap.size > 0 self.replace(result_scrap) end self end
find_index(*args, &block)
click to toggle source
# File lib/gxg/gxg_elements.rb, line 1542 def find_index(*args, &block) result = nil if block.respond_to?(:call) found_at = 0 @data.to_enum(:bytes).each do |the_byte| if block.call(the_byte) == true result = found_at break end found_at += 1 end else if args.size > 0 if args[0].is_a?(Float) args[0] = args[0].to_i end if args[0].is_a?(Integer) if (0..255).include?(args[0]) if args[1] # offset specified (addtional option vs standard Array) result = @data.index(args[0].chr,args[1]) else result = @data.index(args[0].chr) end end else raise TypeError.new("Expected Integer or Float. You provided #{args[0].class}") end else result = @data.to_enum(:bytes) end end result end
first(*args)
click to toggle source
# File lib/gxg/gxg_elements.rb, line 1479 def first(*args) if args.size > 0 if args[0].is_a?(Float) args[0] = args[0].to_i end if args[0].is_a?(Integer) if args[0] > 0 if @max_size unless args[0] <= @max_size raise RangeError.new("#{args[0]} is out of range (1 - #{@max_size}).") end end self[(0..(args[0] - 1))] end else raise TypeError.new("Expected Integer. You provided #{args[0].class}") end else self[0] end end
flatten()
click to toggle source
# File lib/gxg/gxg_elements.rb, line 1501 def flatten() # ByteArray is always flat anyhow self.dclone end
flatten!()
click to toggle source
# File lib/gxg/gxg_elements.rb, line 1506 def flatten!() # ByteArray is always flat anyhow self end
freeze()
click to toggle source
Calls superclass method
# File lib/gxg/gxg_elements.rb, line 1511 def freeze() @data.freeze @max_size.freeze @pad_value.freeze @outer.freeze super() end
get_at_path(the_path="/")
click to toggle source
# File lib/gxg/gxg_elements.rb, line 2191 def get_at_path(the_path="/") # TODO: question: would it serve much to allow ranges as structure-path specifier? What would that involve? # /^(?:[0-9])*[0-9](?:[0-9])*$/ = nil if an alpha present there, else 0 only numeric # Attribution : http://stackoverflow.com/questions/1240674/regex-match-a-string-containing-numbers-and-letters-but-not-a-string-of-just-nu # # if ":" detected do: (str.gsub("%2f","/").to_sym) as key else (str.gsub("%2f","/")) result = nil if the_path == "/" result = self else object_stack = [(self)] path_stack = the_path.split("/") path_stack.to_enum.each do |path_element| element = nil if path_element.size > 0 if (path_element =~ /^(?:[0-9])*[0-9](?:[0-9])*$/) == 0 element = path_element.to_i end end if element result = object_stack.first[(element)] if result.is_a?(NilClass) break else object_stack.unshift(result) end else # ignore double slashes? '//' # break end end end result end
hash()
click to toggle source
# File lib/gxg/gxg_elements.rb, line 1519 def hash() @data.hash end
include?(*args)
click to toggle source
# File lib/gxg/gxg_elements.rb, line 1523 def include?(*args) if args.size > 0 if args[0].is_a?(Float) args[0] = args[0].to_i end if args[0].is_a?(Integer) if (0..255).include?(args[0]) @data.include?(args[0].chr) else raise RangeError.new("Value out of range: range is 0 to 255. You provided #{args[0]}") end else raise TypeError.new("Expected Integer or Float. You provided #{args[0].class}") end else raise ArgumentError.new("Wrong number of arguments (#{args.size} for 1).") end end
initialize_clone()
click to toggle source
# File lib/gxg/gxg_elements.rb, line 868 def initialize_clone() result = self.dclone if self.frozen? result.freeze end result end
initialize_dup()
click to toggle source
# File lib/gxg/gxg_elements.rb, line 876 def initialize_dup() # ByteArry is one-dimensional anyhow self.dclone end
Also aliased as: dup, initialize_copy
insert(*args)
click to toggle source
# File lib/gxg/gxg_elements.rb, line 1577 def insert(*args) if args.size > 1 if args[0].is_a?(Float) args[0] = args[0].to_i end if args[0].is_a?(Integer) value = self.filter_data(args[(1..(args.size - 1))]) if @max_size unless (@data.bytesize + value.bytesize) <= @max_size raise RangeError.new("Operation exceeds #{@max_size} limit. You need to adjust maxsize.") end end begin @data.insert(args[0],value) rescue Exception => error raise error.exception(error.message.gsub("string",(self.class.to_s))) end else raise TypeError.new("Expected Integer or Float. You provided #{args[0].class}") end else raise ArgumentError.new("Wrong number of arguments (#{args.size} for 2).") end self end
inspect()
click to toggle source
# File lib/gxg/gxg_elements.rb, line 1603 def inspect() result = "[" @data.to_enum(:bytes).each do |the_byte| if result.size > 1 result << ", " end if the_byte > 10 result << "0x#{the_byte.to_s(16).upcase}" else result << "0x0#{the_byte.to_s(16).upcase}" end end result << "]" result end
join(*args)
click to toggle source
# File lib/gxg/gxg_elements.rb, line 1619 def join(*args) result = "" if args[1].is_a?(Encoding) # Extra optional encoding vs standard Array result.force_encoding(args[1]) else result.force_encoding(Encoding::ASCII_8BIT) end @data.to_enum(:bytes).each do |the_byte| if (args[0].is_a?(String) && result.size > 0) result << (args[0] + the_byte.chr) else result << the_byte.chr end end result end
last(*args)
click to toggle source
# File lib/gxg/gxg_elements.rb, line 1637 def last(*args) if args.size > 0 if args[0].is_a?(Float) args[0] = args[0].to_i end if args[0].is_a?(Integer) if args[0] > 0 the_range = ((@data.bytesize - 1 - (args[0] - 1))..(@data.bytesize - 1)) if @max_size unless args[0] <= @max_size raise RangeError.new("#{args[0]} is out of range (1 - #{@max_size}).") end end self[(the_range)] else raise RangeError.new("#{args[0]} is out of range (1 - #{@max_size}).") end else raise TypeError.new("Expected Integer. You provided #{args[0].class}") end else self[(@data.bytesize - 1)] end end
match(regular_expression)
click to toggle source
# File lib/gxg/gxg_elements.rb, line 791 def match(regular_expression) @data.match(regular_expression) end
maxsize()
click to toggle source
# File lib/gxg/gxg_elements.rb, line 795 def maxsize() @max_size.clone end
maxsize=(*args)
click to toggle source
# File lib/gxg/gxg_elements.rb, line 799 def maxsize=(*args) # Set @maxsize: Warning: setting @maxsize lower than the @data.bytesize will truncate the data if args.size > 0 if args[0] if args[0].is_a?(Numeric) args[0] = args[0].to_i end # if args[0].is_a?(Integer) if args[0] > GxG::SYSTEM.memory_limits()[:process].first raise NoMemoryError.new("Setting maxsize this high exceeds per-process memory limits") end if args[0] > @max_size.to_i @max_size = args[0] else if args[0] < @max_size.to_i # truncate data if @max_size lowered below @data.bytesize @max_size = args[0] if @data.bytesize > args[0] @data.replace(@data[0..(args[0] - 1)]) end end end else raise ArgumentError.new("Expected NilClass or Numeric class. You provided #{args[0].class}") end else @max_size = nil end else @max_size = nil end @max_size.clone end
mime_type()
click to toggle source
# File lib/gxg/gxg_elements.rb, line 687 def mime_type() @data.mime_type() end
outervalue()
click to toggle source
# File lib/gxg/gxg_elements.rb, line 834 def outervalue() @outer.clone end
outervalue=(*args)
click to toggle source
# File lib/gxg/gxg_elements.rb, line 838 def outervalue=(*args) if args.size > 0 if args[0] if args[0].is_a?(Float) args[0] = args[0].to_i end if args[0].is_a?(Integer) if (0..255).include?(args[0]) @outer = args[0] end else raise TypeError.new("Expected a NilClass, a Float, or a Integer. You provided #{args[0].class}") end else @outer = nil end else @outer = nil end self.outervalue() end
pack(*args)
click to toggle source
# File lib/gxg/gxg_elements.rb, line 1662 def pack(*args) result = "" if args.size >= 1 args[0] = (args[0] || "") if args[0].is_a?(String) if args[1].is_a?(Encoding) # Extra optional encoding vs standard Array result.force_encoding(args[1]) end # LATER: ByteArray.pack: a more memory-efficient method is needed here long term. For now: leverage Array.pack. # Each byte will take up 4 to 8 bytes depending just to get packed into a string ... gotta fix this. result << self.to_a.pack(args[0]) else raise TypeError.new("Expected String. You provided #{args[0].class}") end else raise ArgumentError.new("Wrong number of arguments (#{args.size} for 1+).") end result end
padvalue()
click to toggle source
# File lib/gxg/gxg_elements.rb, line 771 def padvalue() @pad_value.clone end
padvalue=(*args)
click to toggle source
# File lib/gxg/gxg_elements.rb, line 775 def padvalue=(*args) if args.size > 0 if args[0].is_a?(Float) args[0] = args[0].to_i end if args[0].is_a?(Integer) if (0..255).include?(args[0]) @pad_value = args[0] end else raise TypeError.new("Value type: expected Float or Integer. You provided #{args[0].class}") end end @pad_value.clone end
paths_to(object=nil,base_path="")
click to toggle source
GxG Convenience Methods:
# File lib/gxg/gxg_elements.rb, line 2177 def paths_to(object=nil,base_path="") # new idea here: search_results = [] # TODO: if paths can use ranges, expand to use string or byte or int byte or byte-pattern matching to define returned valid path for get/set. if object.is_a?(Numeric) self.to_enum.each_with_index do |entry,index| if entry == object.to_i search_results << (base_path + "/" + index.to_s) end end end search_results end
pattern_range(the_pattern="", initial_offset=0)
click to toggle source
# File lib/gxg/gxg_elements.rb, line 721 def pattern_range(the_pattern="", initial_offset=0) result = nil if the_pattern.is_a?(::ByteArray) the_pattern = the_pattern.to_s end if the_pattern.is_a?(::String) if initial_offset.is_a?(::Integer) if @max_size if initial_offset > @max_size raise ArgumentError, "Offset exceeds the maximum size." end end if the_pattern.encoding != ::Encoding::ASCII_8BIT the_pattern = the_pattern.clone the_pattern.force_encoding(::Encoding::ASCII_8BIT) end offset = @data.index(the_pattern, initial_offset) if offset.is_a?(::Integer) result = ((offset)..(offset + (the_pattern.size - 1))) end else raise ArgumentError, "You MUST provide the offset as an Integer." end else raise ArgumentError, "You MUST provide a String to find." end result end
pattern_ranges(the_pattern="")
click to toggle source
# File lib/gxg/gxg_elements.rb, line 750 def pattern_ranges(the_pattern="") result = [] offset = 0 if the_pattern.is_a?(::ByteArray) the_pattern = the_pattern.to_s end last_found = self.pattern_range(the_pattern,offset) while last_found != nil do if last_found.is_a?(::Range) result << last_found if (last_found.last() + 1) <= @data.bytesize offset = (last_found.last() + 1) else break end end last_found = self.pattern_range(the_pattern,offset) end result end
permutation(*args,&block)
click to toggle source
# File lib/gxg/gxg_elements.rb, line 1683 def permutation(*args,&block) # TODO: port c code to ruby (true-enumeration-as-bytearray support) enumerator = @data.to_enum(:bytes).to_a.to_enum(:permutation,*args) if block.respond_to?(:call) enumerator.each do |the_permutation| block.call(GxG::ByteArray.new(the_permutation)) end self else GxG::Enumerator.new(enumerator) end end
pop(how_many=nil)
click to toggle source
# File lib/gxg/gxg_elements.rb, line 1709 def pop(how_many=nil) # LIFO style stack operation if how_many.is_a?(Numeric) unless how_many.to_i > 0 raise ArgumentError.new("#{how_many} needs to be a positive Numeric") end self.slice!((how_many.to_i * -1),(how_many.to_i)) else self.slice!(-1,1) end end
process(&block)
click to toggle source
# File lib/gxg/gxg_elements.rb, line 691 def process(&block) result = self.clone if block.respond_to?(:call) result.each_with_index do |entry,index| block.call(entry, index, self) end end result end
process!(&block)
click to toggle source
# File lib/gxg/gxg_elements.rb, line 701 def process!(&block) if block.respond_to?(:call) self.replace(self.process(&block).data()) end self end
product(*others,&block)
click to toggle source
# File lib/gxg/gxg_elements.rb, line 1721 def product(*others,&block) if @data.bytesize > 0 others = GxG::ByteArray.new(others) if block.respond_to?(:call) self.each do |the_byte| others.each do |other_byte| block.call(GxG::ByteArray.new([(the_byte),(other_byte)])) end end self else accumulator = GxG::ByteArray.new self.each do |the_byte| others.each do |other_byte| accumulator << the_byte accumulator << other_byte end end accumulator end else self end end
push(*args)
click to toggle source
# File lib/gxg/gxg_elements.rb, line 1746 def push(*args) # LIFO style stack operation self << GxG::ByteArray.new(args) end
rassoc(key=nil)
click to toggle source
# File lib/gxg/gxg_elements.rb, line 1751 def rassoc(key=nil) nil end
Also aliased as: assoc
reject(&block)
click to toggle source
# File lib/gxg/gxg_elements.rb, line 1755 def reject(&block) result = nil if block.respond_to?(:call) result = GxG::ByteArray.new result.padvalue = (@pad_value) if @max_size result.maxsize = (@max_size) end self.to_enum.each do |the_byte| result << the_byte end else result = self.to_enum end result end
reject!(&block)
click to toggle source
# File lib/gxg/gxg_elements.rb, line 1772 def reject!(&block) result = nil if block.respond_to?(:call) purgelist = [] self.each_with_index do |value, index| if block.call(value) == true @data[(index)] = "" purgelist << index end end result = self else result = self.to_a.to_enum(:reject!) end result end
repeated_combination(*args,&block)
click to toggle source
# File lib/gxg/gxg_elements.rb, line 1177 def repeated_combination(*args,&block) # TODO: port c code to ruby (true-enumeration-as-bytearray support) enumerator = @data.to_enum(:bytes).to_a.to_enum(:repeated_combination,*args) if block.respond_to?(:call) enumerator.each do |the_combination| block.call(GxG::ByteArray.new(the_combination)) end self else GxG::Enumerator.new(enumerator) end end
repeated_permutation(*args,&block)
click to toggle source
# File lib/gxg/gxg_elements.rb, line 1696 def repeated_permutation(*args,&block) # TODO: port c code to ruby (true-enumeration-as-bytearray support) enumerator = @data.to_enum(:bytes).to_a.to_enum(:repeated_permutation,*args) if block.respond_to?(:call) enumerator.each do |the_permutation| block.call(GxG::ByteArray.new(the_permutation)) end self else GxG::Enumerator.new(enumerator) end end
replace(*args)
click to toggle source
# File lib/gxg/gxg_elements.rb, line 1789 def replace(*args) # replace data payload while leaving max_size and pad_value untouched, fitting replacement data into in-place constraints if any. if args.size > 0 replacement = nil if args[0].is_a?(::GxG::ByteArray) replacement = args[0].data() end unless replacement.is_a?(::String) replacement = GxG::ByteArray::try_convert(args) if replacement replacement = replacement.data() end end if replacement replacement.force_encoding(Encoding::ASCII_8BIT) if @max_size if replacement.bytesize <= @max_size @data.replace(replacement) else @data.replace(replacement[(0..(@max_size - 1))]) end else @data.replace(replacement) end else raise Exception.new("Could not convert #{args[0].class} to ByteArray") end end self end
reverse()
click to toggle source
# File lib/gxg/gxg_elements.rb, line 1820 def reverse() result = GxG::ByteArray.new(@data.reverse) result.padvalue = (@pad_value.clone) if @max_size result.maxsize = (@max_size.clone) end result end
reverse!()
click to toggle source
# File lib/gxg/gxg_elements.rb, line 1829 def reverse!() @data.reverse! self end
reverse_each(&block)
click to toggle source
# File lib/gxg/gxg_elements.rb, line 1834 def reverse_each(&block) result = nil if block.respond_to?(:call) # use duplicate of self, do not preserve frozen state. result = self.dup result.clear @data.reverse.to_enum(:bytes).each {|the_byte| result << block.call(the_byte)} else # ballons mem footprint x2: *ouch* - don't know a better way yet. result = self.clone.reverse!.to_enum end result end
rotate(vector=1)
click to toggle source
# File lib/gxg/gxg_elements.rb, line 1848 def rotate(vector=1) unless vector.is_a?(Numeric) raise ArgumentError.new("Expected a Numeric, you provided #{vector.class}") end # from array.c : rotate_count if vector < 0 vector = (self.size - (~vector % self.size) - 1).to_i else vector = (vector % self.size).to_i end if GxG::Engine.memory_load_high? # trade speed for (2x) space scrap = [] unless vector == 0 the_range = self.filter_parameters(((vector)..-1)) scrap << self[(the_range)] if the_range.first > 0 scrap << self[(0..(the_range.first - 1))] end end if scrap.size > 0 result = GxG::ByteArray.new(scrap) else result = self.dclone end else # trade (5x) space for speed result = GxG::ByteArray.new(self.to_a.rotate(vector)) end result end
rotate!(vector=1)
click to toggle source
# File lib/gxg/gxg_elements.rb, line 1880 def rotate!(vector=1) if vector.is_a?(Numeric) if vector.to_i != 0 new_data = self.rotate(vector).data() unless @data.hash == new_data.hash self.replace(new_data) end end else raise ArgumentError.new("Expected a Numeric, you provided #{vector.class}") end self end
sample(*args)
click to toggle source
# File lib/gxg/gxg_elements.rb, line 1894 def sample(*args) GxG::ByteArray.new(@data.to_enum(:bytes).to_a.sample(*args)) end
search(&block)
click to toggle source
# File lib/gxg/gxg_elements.rb, line 708 def search(&block) result = [] if block.respond_to?(:call) self.each_with_index do |entry,index| raw_result = block.call(entry,index,self) if raw_result result << raw_result end end end result end
select(&block)
click to toggle source
# File lib/gxg/gxg_elements.rb, line 1898 def select(&block) result = GxG::ByteArray.new result.maxsize = (@max_size) result.padvalue = (@pad_value) result.outervalue = (@outer) if block.respond_to?(:call) self.each do |value| unless block.call(value) == false result << value end end else self.to_enum(:each) end result end
select!(&block)
click to toggle source
# File lib/gxg/gxg_elements.rb, line 1915 def select!(&block) if block.respond_to?(:call) state = @data.hash self.replace(self.select(&block).data()) if state == @data.hash nil else self end else self.to_enum(:each) end end
Also aliased as: keep_if
set_at_path(the_path="/",the_value=nil)
click to toggle source
# File lib/gxg/gxg_elements.rb, line 2226 def set_at_path(the_path="/",the_value=nil) result = nil if the_path != "/" container = self if container raw_selector = ::File::basename(the_path) selector = nil if raw_selector.size > 0 if (raw_selector =~ /^(?:[0-9])*[0-9](?:[0-9])*$/) == 0 selector = raw_selector.to_i end end if selector container[(selector)] = the_value if container[(selector)] == the_value result = true end else # ignore double slashes? '//' # break end # end end result end
shift()
click to toggle source
# File lib/gxg/gxg_elements.rb, line 1929 def shift() # FIFO style pop self.delete_at(0) end
shuffle(*args)
click to toggle source
# File lib/gxg/gxg_elements.rb, line 1934 def shuffle(*args) GxG::ByteArray.new(@data.to_enum(:bytes).to_a.shuffle(*args)) end
shuffle!(*args)
click to toggle source
# File lib/gxg/gxg_elements.rb, line 1938 def shuffle!(*args) self.replace(self.shuffle(*args)) self end
size()
click to toggle source
# File lib/gxg/gxg_elements.rb, line 1943 def size() @data.bytesize end
slice(indexer=0, length=nil)
click to toggle source
# File lib/gxg/gxg_elements.rb, line 1947 def slice(indexer=0, length=nil) the_range = self.filter_parameters(indexer,length) unless the_range if length raise ArgumentError.new("#{indexer.inspect},#{length.inspect} could not be fashioned into a valid Indexer") else raise ArgumentError.new("#{indexer.inspect} could not be fashioned into a valid Indexer") end end # check overall compliance with maxsize if @max_size if ((the_range.count > @max_size) || (the_range.first > (@max_size - 1)) || (the_range.last > (@max_size - 1))) raise IndexError.new("Index exceeds #{@max_size} limit. You need to adjust maxsize.") end end # result = nil # if the_range if the_range.first == the_range.last result = @data.byte_at(the_range.first) else result = @data.bytes_at(the_range) end end # result end
slice!(indexer=0, length=nil)
click to toggle source
# File lib/gxg/gxg_elements.rb, line 1976 def slice!(indexer=0, length=nil) replacement = self.slice(indexer,length) if replacement.is_a?(Numeric) self.replace(replacement.chr) else self.replace(replacement) end if self.size == 1 self.slice(0) else self end end
sort(&block)
click to toggle source
BETA: ByteArray : see about self.to_a replacement (memory efficiency) in sort methods.
# File lib/gxg/gxg_elements.rb, line 1992 def sort(&block) if block.respond_to?(:call) GxG::ByteArray.new(self.to_a.sort {|a,b| pause;block.call(a,b)}) else GxG::ByteArray.new(self.to_a.sort) end end
sort!(&block)
click to toggle source
# File lib/gxg/gxg_elements.rb, line 2000 def sort!(&block) if block.respond_to?(:call) self.replace(self.sort(&block).data()) end self end
sort_by!(&block)
click to toggle source
# File lib/gxg/gxg_elements.rb, line 2007 def sort_by!(&block) if block.respond_to?(:call) self.replace(GxG::ByteArray.new(self.to_a.sort_by! {|a,b| pause;block.call(a,b)}).data()) self else self.to_enum(:sort_by!) end end
take(length)
click to toggle source
# File lib/gxg/gxg_elements.rb, line 2016 def take(length) self.slice(0..(length.to_i - 1)) end
take_while(&block)
click to toggle source
# File lib/gxg/gxg_elements.rb, line 2020 def take_while(&block) if block.respond_to?(:call) accumulator = GxG::ByteArray.new self.each do |the_byte| result = block.call(the_byte) if result accumulator << the_byte else break end end accumulator else self.to_enum(:take_while) end end
to_a()
click to toggle source
# File lib/gxg/gxg_elements.rb, line 2037 def to_a() result = [] if @data.bytesize > 0 (0..(@data.bytesize - 1)).to_enum.each {|index| result << self[(index)]} end result end
Also aliased as: to_ary
to_json()
click to toggle source
# File lib/gxg/gxg_elements.rb, line 2049 def to_json() (("binary:" + self.to_s).encode64) end
to_s()
click to toggle source
# File lib/gxg/gxg_elements.rb, line 2045 def to_s() @data.dup end
transpose()
click to toggle source
# File lib/gxg/gxg_elements.rb, line 2053 def transpose() self.dclone end
uniq(&block)
click to toggle source
# File lib/gxg/gxg_elements.rb, line 2057 def uniq(&block) if block.respond_to?(:call) harness = Proc.new do |element| pause block.call(element) end GxG::ByteArray.new(self.to_a.uniq(&harness)) else self end end
uniq!(&block)
click to toggle source
# File lib/gxg/gxg_elements.rb, line 2069 def uniq!(&block) scrap = self.uniq(&block) if scrap.size == self.size nil else self.replace(scrap) self end end
unshift(*args)
click to toggle source
# File lib/gxg/gxg_elements.rb, line 2079 def unshift(*args) # FIFO style push if args.size > 0 self.insert(0,args) end self end
values_at(*args)
click to toggle source
# File lib/gxg/gxg_elements.rb, line 2087 def values_at(*args) result = GxG::ByteArray.new if args.size > 0 result_scrap = "" result_scrap.force_encoding(Encoding::ASCII_8BIT) args.to_enum.each do |selector| if selector.is_a?(Numeric) or selector.is_a?(Range) unless selector.is_a?(Range) selector = selector.to_i end scrap = self[(selector)] if scrap.is_a?(Integer) result_scrap << scrap.chr else result_scrap << scrap.data() end else raise TypeError.new("Expected Integer, Float or Range. You provided #{selector.class}") end end result = GxG::ByteArray.new(result_scrap) end result end
zip(*args,&block)
click to toggle source
# File lib/gxg/gxg_elements.rb, line 2112 def zip(*args,&block) # Converts any valid argument values to array, then merges elements of self with corresponding elements from each argument # This generates a sequence of self.size n-element ByteArrays as step buffers, where n is one more that the count of arguments # * Then flattened output as ByteArray * # If the size of any argument is less than enumObj.size, @pad_value is supplied # If a block given, it is invoked for each output array. # If block returns an array or ByteArray, it replaces the provided buffer and is appended to output. # result = nil if args.size > 0 result_scrap = "" result_scrap.force_encoding(Encoding::ASCII_8BIT) args.to_enum(:each_index).each do |index| unless args[(index)].is_a?(GxG::ByteArray) args[(index)] = GxG::ByteArray.new(args[(index)]) end end self.each_with_index do |byte,index| # buffer = "" buffer.force_encoding(Encoding::ASCII_8BIT) buffer << byte.chr args.to_enum(:each_index).each do |arg_index| if index >= args[(arg_index)].size buffer << @pad_value.chr else buffer << args[(arg_index)].data()[(index)] end end # if block.respond_to?(:call) # I want to differ from stock array.zip behavior: # I want to have it possible to return the processed buffer back - # to a result ByteArray if result of yield = array/ByteArray. raw_new = block.call(GxG::ByteArray.new(buffer)) if raw_new buffer = GxG::ByteArray.new(raw_new).data() end end result_scrap << buffer end result = GxG::ByteArray.new(result_scrap) else result = self.dclone end result end
|(*args)
click to toggle source
# File lib/gxg/gxg_elements.rb, line 981 def |(*args) scrap = GxG::ByteArray::try_convert(args) result = self.dclone if scrap scrap.each do |byte| unless result.include?(byte) result << byte end end end result end
Protected Instance Methods
filter_data(the_data="")
click to toggle source
# File lib/gxg/gxg_elements.rb, line 445 def filter_data(the_data="") # error_message = ("ByteArray.new expects a String, a Integer or Float between 0 and 255, a nil ( counted as padvalue() ), a ByteArray, or an Array of any of those; you provided #{the_data.inspect}") # unless the_data.is_any?(::NilClass,::String,::Numeric, ::Array, ::GxG::ByteArray) raise Exception.new(error_message) end if the_data.is_a?(::String) the_data = the_data.slice_bytes((0..-1)) end if the_data.is_a?(::Numeric) the_data = the_data.to_i if (0..255).include?(the_data) the_data = the_data.chr the_data.force_encoding(Encoding::ASCII_8BIT) else raise Exception.new(error_message) end end if the_data.is_a?(::GxG::ByteArray) the_data = the_data.data().clone end if the_data.is_a?(::Array) temp_string = "" temp_string.force_encoding(Encoding::ASCII_8BIT) the_data.flatten.to_enum.each do |element| temp_string << self.filter_data(element) end if temp_string.size > 0 the_data = temp_string else the_data = "" the_data.force_encoding(Encoding::ASCII_8BIT) end end unless the_data the_data = @pad_value.to_i.chr the_data.force_encoding(Encoding::ASCII_8BIT) end # the_data end
filter_parameters(*args)
click to toggle source
# File lib/gxg/gxg_elements.rb, line 488 def filter_parameters(*args) the_range = nil if args[0].is_a?(Numeric) args[0] = args[0].to_i if args[0] < 0 args[0] = @data.bytesize + args[0] end the_range = ((args[0])..(args[0])) if args[1].is_a?(Numeric) args[1] = args[1].to_i if args[1] < 1 raise ArgumentError.new("Second parameter needs to be a Numeric greater than 0, you provided #{args[1].inspect}") else the_range = ((args[0])..(args[0] + (args[1] - 1))) end end else if args[0].is_a?(Range) if args[0].first < 0 args[1] = @data.bytesize + args[0].first else args[1] = args[0].first end if args[0].last < 0 args[2] = @data.bytesize + args[0].last else args[2] = args[0].last end if args[1] <= args[2] the_range = ((args[1])..(args[2])) else the_range = ((args[2])..(args[1])) end else raise ArgumentError.new("First parameter needs to be a Numeric or a Range, you provided #{args[0].inspect}") end end the_range end