module Mext # # +Mext::EndlessArray+ # # an +array+ with an internal index which will chug out the +next+ # or the previous value in an endless fashion (i.e. +mod'ding+ # the current index) # class EndlessArray < Array attr_reader :cur, :restart_value # # +Mext::EndlessArray.new(me = [], rv = 0)+ # # create an endless array with a regular array copy. # Another optional argument is the +restart_value+ # (which defaults to 0) # def initialize(me = [], rv = 0) self.replace(me) @cur = @restart_value = rv end # # +next(step = 1)+ # # bumps the current index forward of a +step+ value and returns # the current element of +array+ # def next(step = 1) res = self.current @cur += step @cur = [self.cur % self.size, self.restart_value].max res end # # +previous(step = 1)+ # # bumps the index backwards and returns the # previous element of the +array+ # def previous(step = 1) res = self.current @cur -= step cur_check = @cur - self.restart_value @cur = cur_check < 0 ? (cur_check % self.size) : @cur res end class RestartValueTooLarge < StandardError; end # # +restart_value=(v)+ # # sets the +restart_value+ to +v+. Raises an exception if +v+ is larger # than +self.size - 1+. When set, it changes the current index but only # it is below the +restart_value+ # def restart_value=(v) raise RestartValueTooLarge if v >= self.size @restart_value = v @cur = [@cur, @restart_value].max end # # +current+ # # returns the value stored in the current location # def current self[self.cur] end # # +reset+ # # reset the +current+ pointer to the +restart_value+ # and returns whatever happens to be in it. # def reset @cur = self.restart_value self.current end include Mext::Utilities class << self def from_yaml(ha) raise ArgumentError unless ha.kind_of?(Hash) && ha.has_key?('args') args = ha['args'].map { |value| value.kind_of?(String) ? eval(value) : value } new(args) end end end end