aboutsummaryrefslogtreecommitdiffstats
path: root/vendor/ruby-ole/lib/ole/support.rb
diff options
context:
space:
mode:
Diffstat (limited to 'vendor/ruby-ole/lib/ole/support.rb')
-rw-r--r--vendor/ruby-ole/lib/ole/support.rb256
1 files changed, 256 insertions, 0 deletions
diff --git a/vendor/ruby-ole/lib/ole/support.rb b/vendor/ruby-ole/lib/ole/support.rb
new file mode 100644
index 000000000..bbb0bbe68
--- /dev/null
+++ b/vendor/ruby-ole/lib/ole/support.rb
@@ -0,0 +1,256 @@
+#
+# A file with general support functions used by most files in the project.
+#
+# These are the only methods added to other classes.
+#
+
+require 'logger'
+require 'stringio'
+require 'enumerator'
+
+class String # :nodoc:
+ # plural of String#index. returns all offsets of +string+. rename to indices?
+ #
+ # note that it doesn't check for overlapping values.
+ def indexes string
+ # in some ways i'm surprised that $~ works properly in this case...
+ to_enum(:scan, /#{Regexp.quote string}/m).map { $~.begin 0 }
+ end
+
+ def each_chunk size
+ (length / size.to_f).ceil.times { |i| yield self[i * size, size] }
+ end
+end
+
+class File # :nodoc:
+ # for interface consistency with StringIO etc (rather than adding #stat
+ # to them). used by RangesIO.
+ def size
+ stat.size
+ end
+end
+
+class Symbol # :nodoc:
+ unless :x.respond_to? :to_proc
+ def to_proc
+ proc { |a| a.send self }
+ end
+ end
+end
+
+module Enumerable # :nodoc:
+ unless [].respond_to? :group_by
+ # 1.9 backport
+ def group_by
+ hash = Hash.new { |h, key| h[key] = [] }
+ each { |item| hash[yield(item)] << item }
+ hash
+ end
+ end
+
+ unless [].respond_to? :sum
+ def sum initial=0
+ inject(initial) { |a, b| a + b }
+ end
+ end
+end
+
+# move to support?
+class IO # :nodoc:
+ # Copy data from IO-like object +src+, to +dst+
+ def self.copy src, dst
+ until src.eof?
+ buf = src.read(4096)
+ dst.write buf
+ end
+ end
+end
+
+class Logger # :nodoc:
+ # A helper method for creating a +Logger+ which produce call stack
+ # in their output
+ def self.new_with_callstack logdev=STDERR
+ log = Logger.new logdev
+ log.level = WARN
+ log.formatter = proc do |severity, time, progname, msg|
+ # find where we were called from, in our code
+ callstack = caller.dup
+ callstack.shift while callstack.first =~ /\/logger\.rb:\d+:in/
+ from = callstack.first.sub(/:in `(.*?)'/, ":\\1")
+ "[%s %s]\n%-7s%s\n" % [time.strftime('%H:%M:%S'), from, severity, msg.to_s]
+ end
+ log
+ end
+end
+
+# Include this module into a class that defines #each_child. It should
+# maybe use #each instead, but its easier to be more specific, and use
+# an alias.
+#
+# I don't want to force the class to cache children (eg where children
+# are loaded on request in pst), because that forces the whole tree to
+# be loaded. So, the methods should only call #each_child once, and
+# breadth first iteration holds its own copy of the children around.
+#
+# Main methods are #recursive, and #to_tree
+module RecursivelyEnumerable # :nodoc:
+ def each_recursive_depth_first(&block)
+ each_child do |child|
+ yield child
+ if child.respond_to? :each_recursive_depth_first
+ child.each_recursive_depth_first(&block)
+ end
+ end
+ end
+
+ # don't think this is actually a proper breadth first recursion. only first
+ # level is breadth first.
+ def each_recursive_breadth_first(&block)
+ children = []
+ each_child do |child|
+ children << child if child.respond_to? :each_recursive_breadth_first
+ yield child
+ end
+ children.each { |child| child.each_recursive_breadth_first(&block) }
+ end
+
+ def each_recursive mode=:depth_first, &block
+ # we always actually yield ourself (the tree root) before recursing
+ yield self
+ send "each_recursive_#{mode}", &block
+ end
+
+ # the idea of this function, is to allow use of regular Enumerable methods
+ # in a recursive fashion. eg:
+ #
+ # # just looks at top level children
+ # root.find { |child| child.some_condition? }
+ # # recurse into all children getting non-folders, breadth first
+ # root.recursive(:breadth_first).select { |child| !child.folder? }
+ # # just get everything
+ # items = root.recursive.to_a
+ #
+ def recursive mode=:depth_first
+ to_enum(:each_recursive, mode)
+ end
+
+ # streams a "tree" form of the recursively enumerable structure to +io+, or
+ # return a string form instead if +io+ is not specified.
+ #
+ # mostly a debugging aid. can specify a different block which will be called
+ # to provide the string form for each node.
+ def to_tree io='', &inspect
+ inspect ||= :inspect.to_proc
+ io << "- #{inspect[self]}\n"
+ recurse = proc do |node, prefix|
+ child = nil
+ node.each_child do |next_child|
+ if child
+ io << "#{prefix}|- #{inspect[child]}\n"
+ recurse.call child, prefix + '| '
+ end
+ child = next_child
+ end if node.respond_to?(:each_child)
+ if child
+ io << "#{prefix}\\- #{inspect[child]}\n"
+ recurse.call child, prefix + ' '
+ end
+ end
+ recurse.call self, ' '
+ io
+ end
+end
+
+# can include File::Constants
+class IO
+ # this is for jruby
+ include File::Constants unless defined?(RDONLY)
+
+ # nabbed from rubinius, and modified
+ def self.parse_mode mode
+ ret = 0
+
+ case mode[0, 1]
+ when 'r'; ret |= RDONLY
+ when 'w'; ret |= WRONLY | CREAT | TRUNC
+ when 'a'; ret |= WRONLY | CREAT | APPEND
+ else raise ArgumentError, "illegal access mode #{mode}"
+ end
+
+ (1...mode.length).each do |i|
+ case mode[i, 1]
+ when '+'; ret = (ret & ~(RDONLY | WRONLY)) | RDWR
+ when 'b'; ret |= Mode::BINARY
+ else raise ArgumentError, "illegal access mode #{mode}"
+ end
+ end
+
+ ret
+ end
+
+ class Mode
+ # ruby 1.9 defines binary as 0, which isn't very helpful.
+ # its 4 in rubinius. no longer using
+ #
+ # BINARY = 0x4 unless defined?(BINARY)
+ #
+ # for that reason, have my own constants module here
+ module Constants
+ include File::Constants
+ BINARY = 0x4
+ end
+
+ include Constants
+ NAMES = %w[rdonly wronly rdwr creat trunc append binary]
+
+ attr_reader :flags
+ def initialize flags
+ flags = IO.parse_mode flags.to_str if flags.respond_to? :to_str
+ raise ArgumentError, "invalid flags - #{flags.inspect}" unless Fixnum === flags
+ @flags = flags
+ end
+
+ def writeable?
+ #(@flags & RDONLY) == 0
+ (@flags & 0x3) != RDONLY
+ end
+
+ def readable?
+ (@flags & WRONLY) == 0
+ end
+
+ def truncate?
+ (@flags & TRUNC) != 0
+ end
+
+ def append?
+ (@flags & APPEND) != 0
+ end
+
+ def create?
+ (@flags & CREAT) != 0
+ end
+
+ def binary?
+ (@flags & BINARY) != 0
+ end
+
+=begin
+ # revisit this
+ def apply io
+ if truncate?
+ io.truncate 0
+ elsif append?
+ io.seek IO::SEEK_END, 0
+ end
+ end
+=end
+
+ def inspect
+ names = NAMES.map { |name| name if (flags & Mode.const_get(name.upcase)) != 0 }
+ names.unshift 'rdonly' if (flags & 0x3) == 0
+ "#<#{self.class} #{names.compact * '|'}>"
+ end
+ end
+end
+