# == Copyright
#
# Copyright (c) 2008-2012 thundernet development group, inc.  All rights reserved.
#
# == Author
#
#   Alan Partis
#
# == Synopsis
#
#   Library of various updates to Ruby standard classes and modules to provide
#   commonly needed, or just convenient, features and functions.
#
# == Dependencies
#
#   this file needs to sit in the local directory, the Ruby lib path, or be
#   explicity referenced in the require statement.
#
# == Usage
#
#   require 'tdglib'
#
#

#-------------------------------------------------------------------------------
# Kernel
#++
#   functions defined here are globally available
#-------------------------------------------------------------------------------
module Kernel

    #-------------------------------------------------------------------------------
    # Boolean
    #++
    #   converts a given value to boolean.  True is returned for any string that
    #   looks like 'true' (case insensative) or any numeric non-zero value.  False
    #   for anything else.
    #
    #   This is a derivative work based on work originally found at:
    #
    #       http://chrisroos.co.uk/blog/2006-10-20-boolean-method-in-ruby-sibling-of-array-float-integer-and-string
    #-------------------------------------------------------------------------------
    def Boolean(value)
        if value.class == Fixnum
            return false if value == 0
            return true
        end
        return true if value == true || value =~ /^true$/i
        return false
    end



    #-------------------------------------------------------------------------------
    # hexdump
    #++
    #   Assumes the given argument is an array of 'bytes' i.e.  Fixnum values less
    #   than 256, and prints them out in classic 'od' style.
    #-------------------------------------------------------------------------------
    def hexdump(bytes)
        ascii_rep = ""
        i = 0

        printf(" %04X %04X: ", 0, 0);

        if ((Array == bytes.class) && (Fixnum == bytes[0].class)) then
            bytes.each { |x|
                if (!x.nil?) then
                    printf("%02x ", x)
                    if ((x > 0x1f) && (x < 0x7f)) then ascii_rep += x.chr
                    else                               ascii_rep += '.' end
                else
                    printf("-- ")
                    ascii_rep += '.'
                end

                if ((i % 16) == 15) then
                     printf("   %s\n", ascii_rep)
                     ascii_rep = ""
                    printf(" %04X %04X: ", ((i+1) >> 16), i+1);
                elsif ((i % 8) == 7) then
                    print("  ")
                    ascii_rep += '  '
                end
                i += 1
            }
            # now print spaces until i counts out ...
            if ((i % 16) <= 15) then
                print("   ")
                while ((i % 16) < 15) do
                    print("   ")
                    if ((i % 8) == 7) then
                        print("  ")
                        ascii_rep += '  '
                    end
                    i += 1
                end
                printf("   %s\n", ascii_rep)
            end
        else
            puts '<<< not an array of Fixnum >>>'
        end
    end



    #-------------------------------------------------------------------------------
    # min
    #++
    #   Returns the lesser of the given arguments.  Throws exceptions for missing
    #   arguments or non-comparable types.
    #-------------------------------------------------------------------------------
    def min(a, b)
        return a if a.to_i < b.to_i
        return b
    end



    #-------------------------------------------------------------------------------
    # suppress_warnings
    #++
    #   Provides a 'wrapper' for the given code that will suppress warnings that
    #   might otherwise arise from said code.  Nice for shutting up the interpreter
    #   when you know you're doing something 'naughty.'
    #
    #   usage:
    #
    #       suppress_warnings {
    #           <code that produces warnings>
    #       }
    #
    #   This is copied from work originally found at:
    #
    #       http://mentalized.net/journal/2010/04/02/suppress_warnings_from_ruby/
    #-------------------------------------------------------------------------------
    def suppress_warnings
        # turn down the 'verbosity'
        original_verbosity = $VERBOSE
        $VERBOSE = nil

        # execute the given code
        result = yield

        # turn the heat back on ...
        $VERBOSE = original_verbosity

        return result
    end

end



#-------------------------------------------------------------------------------
# Object
#++
#   Add/modify methods available on all Ruby objects
#-------------------------------------------------------------------------------
class Object

    #-------------------------------------------------------------------------------
    # true?
    #++
    #   tests self for 'trueness' i.e. does it 'look' like true?
    #
    #   args
    #       none
    #
    #   return          true/false
    #-------------------------------------------------------------------------------
    def true?
        Boolean(self)
    end
end


#-------------------------------------------------------------------------------
# Array
#++
#   Add/modify methods available on Array objects
#-------------------------------------------------------------------------------
class Array

    #-------------------------------------------------------------------------------
    # over_thresh
    #++
    # returns a subset array where the elements all exceed
    # a given threshhold value
    #
    # args
    #   thresh          the value to test elements against
    #
    # return            new array containing successful comparisons
    #-------------------------------------------------------------------------------
    def over_thresh(thresh)
        a = Array.new
        self.each { |e|
            a << e if e >= thresh
        }
        a
    end



    #-------------------------------------------------------------------------------
    # mean
    #++
    # returns the statistical mean of all the numeric values in this array.
    # Any non-numeric values will be interpretted as zero and WILL count
    # against the mean.
    #-------------------------------------------------------------------------------
    def mean()
        sum = 0.0
        count = 0
        mean = 0.0

        self.each { |e|
            sum += e.to_f
            count += 1
            mean = sum / count.to_f
        }
        mean
    end

    #-------------------------------------------------------------------------------
    # sum
    #++
    # returns a mathematical sum of numeric values in this array.
    #-------------------------------------------------------------------------------
    def sum()
        sum = 0
        self.each { |e|
            sum += e.to_i
        }
        sum
    end

    #-------------------------------------------------------------------------------
    # xor
    #++
    # returns a new array containing the XOR of the elements between this array and
    #  the given array.  The resulting array is equal in length to the longer of the
    #  operand arrays.
    #-------------------------------------------------------------------------------
    def ^(b)
        result = Array.new
        i = 0
        self.each { |e|
            result << (e ^ (b[i] ? b[i] : 0))
            i += 1
        }
        while (i <= (b.length - 1)) do
            # copy the extra elements of b to the result
            result << b[i]
            i += 1
        end
        return result
    end
    def xor(b)
        self ^ b
    end

end # end of class Array



#-------------------------------------------------------------------------------
# String
#++
#   Add/modify methods available on String objects
#-------------------------------------------------------------------------------
class String

    #-------------------------------------------------------------------------------
    # ends_with?
    #++
    # copied from Rails/Active Support String module -- just in case
    # this module is not already installed locally
    #-------------------------------------------------------------------------------
    def ends_with?(suffix)
        suffix = suffix.to_s
        self[-suffix.length, suffix.length] == suffix
    end



    #-------------------------------------------------------------------------------
    # starts_with?
    #++
    # copied from Rails/Active Support String module -- just in case
    # this module is not already installed locally
    #-------------------------------------------------------------------------------
    def starts_with?(prefix)
        prefix = prefix.to_s
        self[0, prefix.length] == prefix
    end



    #-------------------------------------------------------------------------------
    # hex_bytes
    #++
    # Assuming (without checking) that we are a string of hex digits, translates each
    # pair of digits into an array of Fixnums.
    #-------------------------------------------------------------------------------
    def hex_bytes
        n = Array.new
        self.scan(/../).each do | x |
            n << x.to_i(16)
        end
        n
    end

end # end of class String


  Copyright © Thundernet Development Group Inc., 2003.
All rights reserved.