Skip to content

HTTPS clone URL

Subversion checkout URL

You can clone with
or
.
Download ZIP
Browse files

Module-ize class extensions

Start cleaning up structures
  • Loading branch information...
commit a9ec82523b330dcf083dde6c6e9d1b8e8ea8e36b 1 parent c801163
@test2049 test2049 authored
View
47 extensions/lib/array.rb
@@ -1,24 +1,31 @@
class Array
- # Assume an array of key, value tuples, and convert to Hash
- def to_hash
- r = {}
- each {|it| r[it[0]] = it[1]}
- return r
- end
+ module ArrayExtensions
+ # Assume an array of key, value tuples, and convert to Hash
+ def to_hash
+ r = {}
+ each {|it| r[it[0]] = it[1]}
+ return r
+ end
- def kind_of_these? y
- inject(false) {|acc, klass| acc || y.kind_of?(klass)}
- end
-
- #return first hash-like element with key k
- def kassoc(k)
- each { |h| return h if h.try(:has_key?, k) }
- return nil
- end
-
- #return first hash-like element with value v
- def vassoc(v)
- each { |h| return h if h.try(:has_value?, v) }
- return nil
+ def kind_of_these? y
+ inject(false) {|acc, klass| acc || y.kind_of?(klass)}
+ end
+
+ #return first hash-like element with key k
+ def kassoc(k)
+ each { |h| return h if h.try(:has_key?, k) }
+ return nil
+ end
+
+ #return first hash-like element with value v
+ def vassoc(v)
+ each { |h| return h if h.try(:has_value?, v) }
+ return nil
+ end
+
+ def extract_options!
+ last.is_a?(::Hash) ? pop : {}
+ end
end
+ include ArrayExtensions
end
View
178 extensions/lib/class.rb
@@ -1,29 +1,167 @@
class Class
+ module ClassExtensions
+ # Also crazy that this isn't in the library
+ def inherits_from?(klass)
+ return true if self == klass
+ return true if self.superclass == klass
+ return false if self.superclass == Object
- # Also crazy that this isn't in the library
- def inherits_from?(klass)
- return true if self == klass
- return true if self.superclass == klass
- return false if self.superclass == Object
-
- rec = lambda do |x|
- if x == Object
- false
- elsif x == klass
- true
- else
- rec.call(x.superclass)
+ rec = lambda do |x|
+ if x == Object
+ false
+ elsif x == klass
+ true
+ else
+ rec.call(x.superclass)
+ end
end
+
+ rec.call(self)
end
- rec.call(self)
- end
+ def alias_cmethod(to, from)
+ (class << self;self;end).class_eval {
+ define_method to do |*args|
+ send(from, *args)
+ end
+ }
+ end
+
+
+ # Allows attributes to be shared within an inheritance hierarchy, but where each descendant gets a copy of
+ # their parents' attributes, instead of just a pointer to the same. This means that the child can add elements
+ # to, for example, an array without those additions being shared with either their parent, siblings, or
+ # children, which is unlike the regular class-level attributes that are shared across the entire hierarchy.
+ def class_inheritable_reader(*syms)
+ syms.each do |sym|
+ next if sym.is_a?(Hash)
+ class_eval <<-EOS
+def self.#{sym}
+ read_inheritable_attribute(:#{sym})
+end
+
+def #{sym}
+ self.class.#{sym}
+end
+EOS
+ end
+ end
+
+ def class_inheritable_writer(*syms)
+ options = syms.extract_options!
+ syms.each do |sym|
+ class_eval <<-EOS
+ def self.#{sym}=(obj)
+ write_inheritable_attribute(:#{sym}, obj)
+ end
+
+ #{"
+ def #{sym}=(obj)
+ self.class.#{sym} = obj
+ end
+ " unless options[:instance_writer] == false }
+ EOS
+ end
+ end
+
+ def class_inheritable_array_writer(*syms)
+ options = syms.extract_options!
+ syms.each do |sym|
+ class_eval <<-EOS
+ def self.#{sym}=(obj)
+ write_inheritable_array(:#{sym}, obj)
+ end
+
+ #{"
+ def #{sym}=(obj)
+ self.class.#{sym} = obj
+ end
+ " unless options[:instance_writer] == false }
+ EOS
+ end
+ end
+
+ def class_inheritable_hash_writer(*syms)
+ options = syms.extract_options!
+ syms.each do |sym|
+ class_eval <<-EOS
+ def self.#{sym}=(obj)
+ write_inheritable_hash(:#{sym}, obj)
+ end
+
+ #{"
+ def #{sym}=(obj)
+ self.class.#{sym} = obj
+ end
+ " unless options[:instance_writer] == false }
+ EOS
+ end
+ end
+
+ def class_inheritable_accessor(*syms)
+ class_inheritable_reader(*syms)
+ class_inheritable_writer(*syms)
+ end
+
+ def class_inheritable_array(*syms)
+ class_inheritable_reader(*syms)
+ class_inheritable_array_writer(*syms)
+ end
+
+ def class_inheritable_hash(*syms)
+ class_inheritable_reader(*syms)
+ class_inheritable_hash_writer(*syms)
+ end
+
+ def inheritable_attributes
+ @inheritable_attributes ||= EMPTY_INHERITABLE_ATTRIBUTES
+ end
+
+ def write_inheritable_attribute(key, value)
+ if inheritable_attributes.equal?(EMPTY_INHERITABLE_ATTRIBUTES)
+ @inheritable_attributes = {}
+ end
+ inheritable_attributes[key] = value
+ end
+
+ def write_inheritable_array(key, elements)
+ write_inheritable_attribute(key, []) if read_inheritable_attribute(key).nil?
+ write_inheritable_attribute(key, read_inheritable_attribute(key) + elements)
+ end
- def alias_cmethod(to, from)
- (class << self;self;end).class_eval {
- define_method to do |*args|
- send(from, *args)
+ def write_inheritable_hash(key, hash)
+ write_inheritable_attribute(key, {}) if read_inheritable_attribute(key).nil?
+ write_inheritable_attribute(key, read_inheritable_attribute(key).merge(hash))
+ end
+
+ def read_inheritable_attribute(key)
+ inheritable_attributes[key]
+ end
+
+ def reset_inheritable_attributes
+ @inheritable_attributes = EMPTY_INHERITABLE_ATTRIBUTES
+ end
+private
+
+ # Prevent this constant from being created multiple times
+ EMPTY_INHERITABLE_ATTRIBUTES = {}.freeze unless const_defined?(:EMPTY_INHERITABLE_ATTRIBUTES)
+
+ def inherited_with_inheritable_attributes(child)
+ inherited_without_inheritable_attributes(child) if respond_to?(:inherited_without_inheritable_attributes)
+
+ if inheritable_attributes.equal?(EMPTY_INHERITABLE_ATTRIBUTES)
+ new_inheritable_attributes = EMPTY_INHERITABLE_ATTRIBUTES
+ else
+ new_inheritable_attributes = inheritable_attributes.inject({}) do |memo, (key, value)|
+ memo.update(key => value.duplicable? ? value.dup : value)
+ end
end
- }
+
+ child.instance_variable_set('@inheritable_attributes', new_inheritable_attributes)
+ end
end
+
+ include ClassExtensions
+ alias inherited_without_inheritable_attributes inherited
+ alias inherited inherited_with_inheritable_attributes
end
View
37 extensions/lib/duplicable.rb
@@ -0,0 +1,37 @@
+class Object
+ # Can you safely .dup this object?
+ # False for nil, false, true, symbols, and numbers; true otherwise.
+ def duplicable?
+ true
+ end
+end
+
+class NilClass #:nodoc:
+ def duplicable?
+ false
+ end
+end
+
+class FalseClass #:nodoc:
+ def duplicable?
+ false
+ end
+end
+
+class TrueClass #:nodoc:
+ def duplicable?
+ false
+ end
+end
+
+class Symbol #:nodoc:
+ def duplicable?
+ false
+ end
+end
+
+class Numeric #:nodoc:
+ def duplicable?
+ false
+ end
+end
View
21 extensions/lib/file.rb
@@ -1,14 +1,17 @@
class File
- def self.mkfifo(name, mode="666", open_mode="r")
- if File.exists? name and File.pipe? name # Leftover from before
- File.delete name
- end
+ module FileExtensions
+ def self.mkfifo(name, mode="666", open_mode="r")
+ if File.exists? name and File.pipe? name # Leftover from before
+ File.delete name
+ end
- # apalling, but ruby/dl has x-p problems
- if ! File.exists? name
- `mkfifo -m #{ mode } #{ name }`
- end
+ # apalling, but ruby/dl has x-p problems
+ if ! File.exists? name
+ `mkfifo -m #{ mode } #{ name }`
+ end
- return File.open(name, open_mode)
+ return File.open(name, open_mode)
+ end
end
+ include FileExtensions
end
View
35 extensions/lib/fixnum.rb
@@ -1,22 +1,25 @@
class Fixnum
- # Ridiculous that this isn't in the library.
- def printable?; self >= 0x20 and self <= 0x7e; end
+ module FixnumExtensions
+ # Ridiculous that this isn't in the library.
+ def printable?; self >= 0x20 and self <= 0x7e; end
- # Like Numeric#Step, but yields the length of each span along with
- # the offset. Useful for stepping through data in increments:
- # 0.stepwith(buffer.size, 4096) {|off,len| pp buffer[off,len]}
- # The "len" parameter accounts for the inevitable short final block.
- def stepwith(limit, stepv, &block)
- step(limit, stepv) do |i|
- remt = limit - i
- yield i, remt.cap(stepv)
- end
- end
+ # Like Numeric#Step, but yields the length of each span along with
+ # the offset. Useful for stepping through data in increments:
+ # 0.stepwith(buffer.size, 4096) {|off,len| pp buffer[off,len]}
+ # The "len" parameter accounts for the inevitable short final block.
+ def stepwith(limit, stepv, &block)
+ step(limit, stepv) do |i|
+ remt = limit - i
+ yield i, remt.cap(stepv)
+ end
+ end
- # you can't clone a fixnum? Why?
- def clone; self; end
+ # you can't clone a fixnum? Why?
+ def clone; self; end
- def upper?; self >= 0x41 and self <= 0x5a; end
- def lower?; self >= 0x61 and self <= 0x7a; end
+ def upper?; self >= 0x41 and self <= 0x5a; end
+ def lower?; self >= 0x61 and self <= 0x7a; end
+ end
+ include FixnumExtensions
end
View
9 extensions/lib/hash.rb
@@ -1,6 +1,9 @@
class Hash
- # XXX does the same thing as Hash#invert i think?
- def flip
- map {|k,v| [v,k]}.to_hash
+ module HashExtensions
+ # XXX does the same thing as Hash#invert i think?
+ def flip
+ map {|k,v| [v,k]}.to_hash
+ end
end
+ include HashExtensions
end
View
39 extensions/lib/integer.rb
@@ -1,23 +1,26 @@
class Integer
- # Convert integers to binary strings
- def to_l32; [self].pack "L"; end
- def to_b32; [self].pack "N"; end
- def to_l16; [self].pack "v"; end
- def to_b16; [self].pack "n"; end
- def to_u8; [self].pack "C"; end
+ module IntegerExtensions
+ # Convert integers to binary strings
+ def to_l32; [self].pack "L"; end
+ def to_b32; [self].pack "N"; end
+ def to_l16; [self].pack "v"; end
+ def to_b16; [self].pack "n"; end
+ def to_u8; [self].pack "C"; end
- # Print a number in hex
- def to_hex(pre="0x"); pre + to_s(16); end
+ # Print a number in hex
+ def to_hex(pre="0x"); pre + to_s(16); end
- # Print a number in binary
- def to_b(pre=""); pre + to_s(2); end
-
- def ffs
- i = 0
- v = self
- while((v >>= 1) != 0)
- i += 1
- end
- return i
+ # Print a number in binary
+ def to_b(pre=""); pre + to_s(2); end
+
+ def ffs
+ i = 0
+ v = self
+ while((v >>= 1) != 0)
+ i += 1
+ end
+ return i
+ end
end
+ include IntegerExtensions
end
View
180 extensions/lib/ipaddr.rb
@@ -3,136 +3,140 @@
class IPAddr
attr_reader :mask_addr
- # ---------------------------------------------------------
+ module IPAddrExtensions
- # make an IP address take the int32 value provided
+ # ---------------------------------------------------------
- def set_int(ip)
- set(ip, Socket::AF_INET)
- end
+ # make an IP address take the int32 value provided
- # ---------------------------------------------------------
+ def set_int(ip)
+ set(ip, Socket::AF_INET)
+ end
- # randomize the "host" part of the IP address (destructive)
+ # ---------------------------------------------------------
- def random(mask=0xFFFFFFFF)
- r = rand(0xFFFFFFFF) & mask
- i = self.to_i & (~mask)
- self.set_int(i | r)
- end
+ # randomize the "host" part of the IP address (destructive)
- alias_method :random!, :random
+ def random(mask=0xFFFFFFFF)
+ r = rand(0xFFFFFFFF) & mask
+ i = self.to_i & (~mask)
+ self.set_int(i | r)
+ end
- # ---------------------------------------------------------
+ alias_method :random!, :random
- # convert a string to IP
+ # ---------------------------------------------------------
- def inet_addr(str)
- in_addr(str)
- end
+ # convert a string to IP
+
+ def inet_addr(str)
+ in_addr(str)
+ end
- # ---------------------------------------------------------
+ # ---------------------------------------------------------
- # construct an IPAddr from a dotted quad string or integer
+ # construct an IPAddr from a dotted quad string or integer
- def IPAddr.inet_addr(str)
- if str.kind_of? String
- IPAddr.lite(str).to_i
- else
- i = IPAddr.new(0, Socket::AF_INET)
- i.set_int(str)
- return i
+ def IPAddr.inet_addr(str)
+ if str.kind_of? String
+ IPAddr.lite(str).to_i
+ else
+ i = IPAddr.new(0, Socket::AF_INET)
+ i.set_int(str)
+ return i
+ end
end
- end
- # ---------------------------------------------------------
+ # ---------------------------------------------------------
- # construct an IPAddr from a dotted quad string without
- # incurring a reverse lookup.
+ # construct an IPAddr from a dotted quad string without
+ # incurring a reverse lookup.
- def IPAddr.lite(str)
- ip = IPAddr.new(0, Socket::AF_INET)
+ def IPAddr.lite(str)
+ ip = IPAddr.new(0, Socket::AF_INET)
- parts = str.split "/"
+ parts = str.split "/"
- ip.set_int(ip.inet_addr(parts[0]))
- ip = ip.mask parts[1] if parts[1]
- return ip
- end
+ ip.set_int(ip.inet_addr(parts[0]))
+ ip = ip.mask parts[1] if parts[1]
+ return ip
+ end
- # ---------------------------------------------------------
+ # ---------------------------------------------------------
- # Convert 255.255.255.0 to 24
+ # Convert 255.255.255.0 to 24
- def self.mask2mlen(mask)
- len = 0
- while len < 32 && mask & 0x80000000 != 0
- mask <<= 1
- mask &= 0xFFFFFFFF
- len += 1
+ def self.mask2mlen(mask)
+ len = 0
+ while len < 32 && mask & 0x80000000 != 0
+ mask <<= 1
+ mask &= 0xFFFFFFFF
+ len += 1
+ end
+ return len
end
- return len
- end
- # ---------------------------------------------------------
+ # ---------------------------------------------------------
- # to_s with a cidr prefix at the end
+ # to_s with a cidr prefix at the end
- def to_cidr_s
- "#{ to_s }/#{ self.class.mask2mlen(@mask_addr) }"
- end
+ def to_cidr_s
+ "#{ to_s }/#{ self.class.mask2mlen(@mask_addr) }"
+ end
- # ---------------------------------------------------------
+ # ---------------------------------------------------------
- # get the mask length
+ # get the mask length
- def to_mlen
- mask = self.to_i
- self.class.mask2mlen(mask)
- end
+ def to_mlen
+ mask = self.to_i
+ self.class.mask2mlen(mask)
+ end
- # ---------------------------------------------------------
+ # ---------------------------------------------------------
- # get the highest address in the range defined by the netmask
+ # get the highest address in the range defined by the netmask
- def top
- IPAddr.inet_addr(self.to_i | (0xFFFFFFFF & (~self.mask_addr)))
- end
+ def top
+ IPAddr.inet_addr(self.to_i | (0xFFFFFFFF & (~self.mask_addr)))
+ end
- # ---------------------------------------------------------
+ # ---------------------------------------------------------
- # get the lowest address in the range defined by the netmask
+ # get the lowest address in the range defined by the netmask
- def bottom
- IPAddr.inet_addr(self.to_i & self.mask_addr)
- end
+ def bottom
+ IPAddr.inet_addr(self.to_i & self.mask_addr)
+ end
- # ---------------------------------------------------------
+ # ---------------------------------------------------------
- # get a random address from within the range defined by the
- # netmask.
+ # get a random address from within the range defined by the
+ # netmask.
- def choice
- return self.clone if self.mask_addr == 0xFFFFFFFF
+ def choice
+ return self.clone if self.mask_addr == 0xFFFFFFFF
- span = self.top.to_i - self.bottom.to_i
- x = self.clone
- x.set_int(self.bottom.to_i + rand(span))
- return x
- end
+ span = self.top.to_i - self.bottom.to_i
+ x = self.clone
+ x.set_int(self.bottom.to_i + rand(span))
+ return x
+ end
- # ---------------------------------------------------------
+ # ---------------------------------------------------------
- # test if the address provided is in the range defined by the
- # netmask
+ # test if the address provided is in the range defined by the
+ # netmask
- def contains(i)
- if not i.kind_of? IPAddr
- i = IPAddr.inet_addr i
+ def contains(i)
+ if not i.kind_of? IPAddr
+ i = IPAddr.inet_addr i
+ end
+
+ i.to_i >= self.bottom.to_i and i.to_i <= self.top.to_i
end
- i.to_i >= self.bottom.to_i and i.to_i <= self.top.to_i
+ alias_method :contains?, :contains
end
-
- alias_method :contains?, :contains
+ include IPAddrExtensions
end
View
55 extensions/lib/module.rb
@@ -1,31 +1,34 @@
class Module
- def to_name_hash
- @name_hash ||= constants.map {|k| [k.intern, const_get(k.intern)]}.to_hash
- end
+ module ModuleExtensions
+ def to_name_hash
+ @name_hash ||= constants.map {|k| [k.intern, const_get(k.intern)]}.to_hash
+ end
- def to_key_hash
- @key_hash ||= constants.map {|k| [const_get(k.intern), k.intern]}.to_hash
- end
-
- def flag_dump(i)
- @bit_map ||= constants.map do |k|
- [k, const_get(k.intern).ffs]
- end.sort {|x, y| x[1] <=> y[1]}
+ def to_key_hash
+ @key_hash ||= constants.map {|k| [const_get(k.intern), k.intern]}.to_hash
+ end
- last = 0
- r = ""
- @bit_map.each do |tup|
- if((v = (tup[1] - last)) > 1)
- r << ("." * (v-1))
- end
+ def flag_dump(i)
+ @bit_map ||= constants.map do |k|
+ [k, const_get(k.intern).ffs]
+ end.sort {|x, y| x[1] <=> y[1]}
- if((i & (1 << tup[1])) != 0)
- r << tup[0][0].chr
- else
- r << tup[0][0].chr.downcase
- end
- last = tup[1]
- end
- return r.reverse
- end
+ last = 0
+ r = ""
+ @bit_map.each do |tup|
+ if((v = (tup[1] - last)) > 1)
+ r << ("." * (v-1))
+ end
+
+ if((i & (1 << tup[1])) != 0)
+ r << tup[0][0].chr
+ else
+ r << tup[0][0].chr.downcase
+ end
+ last = tup[1]
+ end
+ return r.reverse
+ end
+ end
+ include ModuleExtensions
end
View
196 extensions/lib/numeric.rb
@@ -1,106 +1,110 @@
class Numeric
- # This HAS TO BE in the library somewhere already, but: give a fixnum,
- # cap it at some number (ie, max(x, y) -> x). 10.cap(9) => 9.
- def cap(limit); self > limit ? limit : self; end
+ module NumericExtensions
+ # This HAS TO BE in the library somewhere already, but: give a fixnum,
+ # cap it at some number (ie, max(x, y) -> x). 10.cap(9) => 9.
+ def cap(limit); self > limit ? limit : self; end
- def to_x; to_s(16).rjust(8, "0"); end
+ def to_x; to_s(16).rjust(8, "0"); end
- def to_l32
- [self].pack("L")
- end
+ def to_l32
+ [self].pack("L")
+ end
- def to_l16
- [self].pack("v")
- end
+ def to_l16
+ [self].pack("v")
+ end
- def to_l8
- (self&0xFF).chr
- end
+ def to_l8
+ (self&0xFF).chr
+ end
- # sign extend
- def sx8; ([self].pack "c").unpack("C").first; end
- def sx16; ([self].pack "s").unpack("S").first; end
- def sx32; ([self].pack "l").unpack("L").first; end
+ # sign extend
+ def sx8; ([self].pack "c").unpack("C").first; end
+ def sx16; ([self].pack "s").unpack("S").first; end
+ def sx32; ([self].pack "l").unpack("L").first; end
- # Make a bitmask with m-many bits, as an Integer
- def self.mask_for(m)
- # This is just table lookup for values less than 65
-
- @@mask ||= {
- 1 => 0x1,
- 2 => 0x3,
- 3 => 0x7,
- 4 => 0xf,
- 5 => 0x1f,
- 6 => 0x3f,
- 7 => 0x7f,
- 8 => 0xff,
- 9 => 0x1ff,
- 10 => 0x3ff,
- 11 => 0x7ff,
- 12 => 0xfff,
- 13 => 0x1fff,
- 14 => 0x3fff,
- 15 => 0x7fff,
- 16 => 0xffff,
- 17 => 0x1ffff,
- 18 => 0x3ffff,
- 19 => 0x7ffff,
- 20 => 0xfffff,
- 21 => 0x1fffff,
- 22 => 0x3fffff,
- 23 => 0x7fffff,
- 24 => 0xffffff,
- 25 => 0x1ffffff,
- 26 => 0x3ffffff,
- 27 => 0x7ffffff,
- 28 => 0xfffffff,
- 29 => 0x1fffffff,
- 30 => 0x3fffffff,
- 31 => 0x7fffffff,
- 32 => 0xffffffff,
- 33 => 0x1ffffffff,
- 34 => 0x3ffffffff,
- 35 => 0x7ffffffff,
- 36 => 0xfffffffff,
- 37 => 0x1fffffffff,
- 38 => 0x3fffffffff,
- 39 => 0x7fffffffff,
- 40 => 0xffffffffff,
- 41 => 0x1ffffffffff,
- 42 => 0x3ffffffffff,
- 43 => 0x7ffffffffff,
- 44 => 0xfffffffffff,
- 45 => 0x1fffffffffff,
- 46 => 0x3fffffffffff,
- 47 => 0x7fffffffffff,
- 48 => 0xffffffffffff,
- 49 => 0x1ffffffffffff,
- 50 => 0x3ffffffffffff,
- 51 => 0x7ffffffffffff,
- 52 => 0xfffffffffffff,
- 53 => 0x1fffffffffffff,
- 54 => 0x3fffffffffffff,
- 55 => 0x7fffffffffffff,
- 56 => 0xffffffffffffff,
- 57 => 0x1ffffffffffffff,
- 58 => 0x3ffffffffffffff,
- 59 => 0x7ffffffffffffff,
- 60 => 0xfffffffffffffff,
- 61 => 0x1fffffffffffffff,
- 62 => 0x3fffffffffffffff,
- 63 => 0x7fffffffffffffff,
- 64 => 0xffffffffffffffff
- }
+ # Make a bitmask with m-many bits, as an Integer
+ def self.mask_for(m)
+ # This is just table lookup for values less than 65
- if (v = @@mask[m])
- return v
+ @@mask ||= {
+ 1 => 0x1,
+ 2 => 0x3,
+ 3 => 0x7,
+ 4 => 0xf,
+ 5 => 0x1f,
+ 6 => 0x3f,
+ 7 => 0x7f,
+ 8 => 0xff,
+ 9 => 0x1ff,
+ 10 => 0x3ff,
+ 11 => 0x7ff,
+ 12 => 0xfff,
+ 13 => 0x1fff,
+ 14 => 0x3fff,
+ 15 => 0x7fff,
+ 16 => 0xffff,
+ 17 => 0x1ffff,
+ 18 => 0x3ffff,
+ 19 => 0x7ffff,
+ 20 => 0xfffff,
+ 21 => 0x1fffff,
+ 22 => 0x3fffff,
+ 23 => 0x7fffff,
+ 24 => 0xffffff,
+ 25 => 0x1ffffff,
+ 26 => 0x3ffffff,
+ 27 => 0x7ffffff,
+ 28 => 0xfffffff,
+ 29 => 0x1fffffff,
+ 30 => 0x3fffffff,
+ 31 => 0x7fffffff,
+ 32 => 0xffffffff,
+ 33 => 0x1ffffffff,
+ 34 => 0x3ffffffff,
+ 35 => 0x7ffffffff,
+ 36 => 0xfffffffff,
+ 37 => 0x1fffffffff,
+ 38 => 0x3fffffffff,
+ 39 => 0x7fffffffff,
+ 40 => 0xffffffffff,
+ 41 => 0x1ffffffffff,
+ 42 => 0x3ffffffffff,
+ 43 => 0x7ffffffffff,
+ 44 => 0xfffffffffff,
+ 45 => 0x1fffffffffff,
+ 46 => 0x3fffffffffff,
+ 47 => 0x7fffffffffff,
+ 48 => 0xffffffffffff,
+ 49 => 0x1ffffffffffff,
+ 50 => 0x3ffffffffffff,
+ 51 => 0x7ffffffffffff,
+ 52 => 0xfffffffffffff,
+ 53 => 0x1fffffffffffff,
+ 54 => 0x3fffffffffffff,
+ 55 => 0x7fffffffffffff,
+ 56 => 0xffffffffffffff,
+ 57 => 0x1ffffffffffffff,
+ 58 => 0x3ffffffffffffff,
+ 59 => 0x7ffffffffffffff,
+ 60 => 0xfffffffffffffff,
+ 61 => 0x1fffffffffffffff,
+ 62 => 0x3fffffffffffffff,
+ 63 => 0x7fffffffffffffff,
+ 64 => 0xffffffffffffffff
+ }
+
+ if (v = @@mask[m])
+ return v
+ end
+
+ # Compute it for crazy values.
+
+ r = 0
+ 0.upto(m-1) {|q| r |= (1 << q)}
+ return r
+ end
end
-
- # Compute it for crazy values.
-
- r = 0
- 0.upto(m-1) {|q| r |= (1 << q)}
- return r
- end
+
+ include NumericExtensions
end
View
27 extensions/lib/object.rb
@@ -1,19 +1,22 @@
class Object
- # Every object has a "singleton" class, which you can think
- # of as the class (ie, 1.metaclass =~ Fixnum) --- but that you
- # can modify and extend without fucking up the actual class.
+ module ObjectExtensions
+ # Every object has a "singleton" class, which you can think
+ # of as the class (ie, 1.metaclass =~ Fixnum) --- but that you
+ # can modify and extend without fucking up the actual class.
- def metaclass; class << self; self; end; end
- def meta_eval(&blk) metaclass.instance_eval &blk; end
- def meta_def(name, &blk) meta_eval { define_method name, &blk }; end
- def try(meth, *args); send(meth, *args) if respond_to? meth; end
+ def metaclass; class << self; self; end; end
+ def meta_eval(&blk) metaclass.instance_eval &blk; end
+ def meta_def(name, &blk) meta_eval { define_method name, &blk }; end
+ def try(meth, *args); send(meth, *args) if respond_to? meth; end
- def through(meth, *args)
- if respond_to? meth
- send(meth, *args)
- else
- self
+ def through(meth, *args)
+ if respond_to? meth
+ send(meth, *args)
+ else
+ self
+ end
end
end
+ include ObjectExtensions
end
View
23 extensions/lib/range.rb
@@ -1,13 +1,16 @@
class Range
- # again, surprised this isn't in the library
- def each_backwards
- max.to_i.downto(min) {|i| yield i}
- end
+ module RangeExtensions
+ # again, surprised this isn't in the library
+ def each_backwards
+ max.to_i.downto(min) {|i| yield i}
+ end
- # Take a random number out of a range
- #
- def choice
- rand(self.last - self.first) + self.first
- end
- alias_method :choose, :choice
+ # Take a random number out of a range
+ #
+ def choice
+ rand(self.last - self.first) + self.first
+ end
+ alias_method :choose, :choice
+ end
+ include RangeExtensions
end
View
17 extensions/lib/socket.rb
@@ -1,11 +1,14 @@
class Socket
- def self.addr(host, port=nil)
- if not port
- raise "bad!" if not host =~ /(.*):(.*)/
- host = $1
- port = $2
+ module SocketExtensions
+ def self.addr(host, port=nil)
+ if not port
+ raise "bad!" if not host =~ /(.*):(.*)/
+ host = $1
+ port = $2
+ end
+ port = port.to_i
+ Socket.pack_sockaddr_in(port, host)
end
- port = port.to_i
- Socket.pack_sockaddr_in(port, host)
end
+ include SocketExtensions
end
View
541 extensions/lib/string.rb
@@ -1,322 +1,325 @@
%w[iconv stringio].each {|x| require x}
class String
- # Convert a string to "Unicode", ie, the way Win32 expects it, including
- # trailing NUL.
- def to_utf16
- Iconv.iconv("utf-16LE", "utf-8", self).first + "\x00\x00"
- end
-
- # Convert a "Unicode" (Win32-style) string back to native Ruby UTF-8;
- # get rid of any trailing NUL.
- def from_utf16
- ret = Iconv.iconv("utf-8", "utf-16le", self).first
- if ret[-1] == 0
- ret = ret[0..-2]
+ module StringExtensions
+ # Convert a string to "Unicode", ie, the way Win32 expects it, including
+ # trailing NUL.
+ def to_utf16
+ Iconv.iconv("utf-16LE", "utf-8", self).first + "\x00\x00"
end
- end
- alias_method :to_utf8, :from_utf16
- alias_method :to_ascii, :from_utf16
-
- # Convenience for parsing UNICODE strings from a buffer
- # Assumes last char ends in 00, which is not always true but works in English
- def from_utf16_buffer
- self[0..index("\0\0\0")+2].from_utf16
- end
- # Sometimes string buffers passed through Win32 interfaces come with
- # garbage after the trailing NUL; this method gets rid of that, like
- # String#trim
- def asciiz
- begin
- self[0..self.index("\x00")-1]
- rescue
- self
- end
- end
-
- # My entry into the hexdump race. Outputs canonical hexdump, uses
- # StringIO for speed, could be cleaned up with "ljust", and should
- # probably use table lookup instead of to_s(16) method calls.
- def hexdump(capture=false)
- sio = StringIO.new
- rem = size - 1
- off = 0
-
- while rem > 0
- pbuf = ""
- pad = (15 - rem) if rem < 16
- pad ||= 0
-
- sio.write(("0" * (8 - (x = off.to_s(16)).size)) + x + " ")
-
- 0.upto(15-pad) do |i|
- c = self[off]
- x = c.to_s(16)
- sio.write(("0" * (2 - x.size)) + x + " ")
- if c.printable?
- pbuf << c
- else
- pbuf << "."
- end
- off += 1
- rem -= 1
- sio.write(" ") if i == 7
+ # Convert a "Unicode" (Win32-style) string back to native Ruby UTF-8;
+ # get rid of any trailing NUL.
+ def from_utf16
+ ret = Iconv.iconv("utf-8", "utf-16le", self).first
+ if ret[-1] == 0
+ ret = ret[0..-2]
end
-
- sio.write("-- " * pad) if pad > 0
- sio.write(" |#{ pbuf }|\n")
end
+ alias_method :to_utf8, :from_utf16
+ alias_method :to_ascii, :from_utf16
- sio.rewind()
- if capture
- sio.read()
- else
- puts sio.read()
+ # Convenience for parsing UNICODE strings from a buffer
+ # Assumes last char ends in 00, which is not always true but works in English
+ def from_utf16_buffer
+ self[0..index("\0\0\0")+2].from_utf16
end
- end
- # convert a string to its idiomatic ruby class name
- def class_name
- r = ""
- up = true
- each_byte do |c|
- if c == 95
- if up
- r << "::"
- else
- up = true
- end
- else
- m = up ? :upcase : :to_s
- r << (c.chr.send(m))
- up = false
+ # Sometimes string buffers passed through Win32 interfaces come with
+ # garbage after the trailing NUL; this method gets rid of that, like
+ # String#trim
+ def asciiz
+ begin
+ self[0..self.index("\x00")-1]
+ rescue
+ self
end
end
- r
- end
- # Insane that this isn't in the library by default.
- def starts_with? x
- self[0..x.size-1] == x
- end
+ # My entry into the hexdump race. Outputs canonical hexdump, uses
+ # StringIO for speed, could be cleaned up with "ljust", and should
+ # probably use table lookup instead of to_s(16) method calls.
+ def hexdump(capture=false)
+ sio = StringIO.new
+ rem = size - 1
+ off = 0
- def ends_with? x
- self[-(x.size)..-1] == x
- end
+ while rem > 0
+ pbuf = ""
+ pad = (15 - rem) if rem < 16
+ pad ||= 0
- # Cribbed from Ero Carrera's pefile; a relatively expensive entropy
- # function, gives a float result of random-bits-per-byte.
- def entropy
- e = 0
- 0.upto(255) do |i|
- x = count(i.chr)/size.to_f
- if x > 0
- e += - x * Math.log2(x)
- end
- end
+ sio.write(("0" * (8 - (x = off.to_s(16)).size)) + x + " ")
- return e
- end
-
- # The driver function for String#strings below; really, this will
- # run on any Enumerable that contains Fixnums.
- def nextstring(opts={})
- off = opts[:offset] || 0
- sz = opts[:minimum] || 7
- u = opts[:unicode] || false
- l = size
- i = off
- while i < l
- if self[i].printable?
- start = i
- cnt = 1
- i += 1
- lastu = false
- while i < l
- if self[i].printable?
- lastu = false
- cnt += 1
- i += 1
- elsif u and self[i] == 0 and not lastu
- lastu = true
- i += 1
+ 0.upto(15-pad) do |i|
+ c = self[off]
+ x = c.to_s(16)
+ sio.write(("0" * (2 - x.size)) + x + " ")
+ if c.printable?
+ pbuf << c
else
- break
+ pbuf << "."
end
+ off += 1
+ rem -= 1
+ sio.write(" ") if i == 7
end
- return([start, i - start]) if cnt >= sz
+ sio.write("-- " * pad) if pad > 0
+ sio.write(" |#{ pbuf }|\n")
+ end
+
+ sio.rewind()
+ if capture
+ sio.read()
else
- i += 1
+ puts sio.read()
end
end
- return false, false
- end
+ # convert a string to its idiomatic ruby class name
+ def class_name
+ r = ""
+ up = true
+ each_byte do |c|
+ if c == 95
+ if up
+ r << "::"
+ else
+ up = true
+ end
+ else
+ m = up ? :upcase : :to_s
+ r << (c.chr.send(m))
+ up = false
+ end
+ end
+ r
+ end
- # A la Unix strings(1). With a block, yields offset, string length,
- # and contents. Otherwise returns a list. Accepts options:
- # :unicode: superficial but effective Win32 Unicode support, skips NULs
- # :minimum: minimum length of returned strings, ala strings -10
- def strings(opts={})
- ret = []
- opts[:offset] ||= 0
- while 1
- off, size = nextstring(opts)
- break if not off
- opts[:offset] += (off + size)
- if block_given?
- yield off, size, self[off,size]
- else
- ret << [off, size, self[off,size]]
+ # Insane that this isn't in the library by default.
+ def starts_with? x
+ self[0..x.size-1] == x
+ end
+
+ def ends_with? x
+ self[-(x.size)..-1] == x
+ end
+
+ # Cribbed from Ero Carrera's pefile; a relatively expensive entropy
+ # function, gives a float result of random-bits-per-byte.
+ def entropy
+ e = 0
+ 0.upto(255) do |i|
+ x = count(i.chr)/size.to_f
+ if x > 0
+ e += - x * Math.log2(x)
+ end
end
+
+ return e
end
- ret
- end
- # A hacked up adler16 checksum, a la Andrew Tridgell. This is probably
- # even slower than Ruby's native CRC support. A weak, trivial checksum,
- # part of rsync.
- def adler
- a, b = 0, 0
- 0.upto(size-1) {|i| a += self[i]}
- a %= 65536
- 0.upto(size-1) {|i| b += ((size-i)+1) * self[i]}
- b %= 65536
- return (a|(b<<16))
- end
+ # The driver function for String#strings below; really, this will
+ # run on any Enumerable that contains Fixnums.
+ def nextstring(opts={})
+ off = opts[:offset] || 0
+ sz = opts[:minimum] || 7
+ u = opts[:unicode] || false
+ l = size
+ i = off
+ while i < l
+ if self[i].printable?
+ start = i
+ cnt = 1
+ i += 1
+ lastu = false
+ while i < l
+ if self[i].printable?
+ lastu = false
+ cnt += 1
+ i += 1
+ elsif u and self[i] == 0 and not lastu
+ lastu = true
+ i += 1
+ else
+ break
+ end
+ end
- # Convert binary strings back to integers
- def to_l32; unpack("L").first; end
- def to_b32; unpack("N").first; end
- def to_l16; unpack("v").first; end
- def to_b16; unpack("n").first; end
- def to_u8; self[0]; end
- def shift_l32; shift(4).to_l32; end
- def shift_b32; shift(4).to_b32; end
- def shift_l16; shift(2).to_l16; end
- def shift_b16; shift(2).to_b16; end
- def shift_u8; shift(1).to_u8; end
-
- # oh, it's exactly what it sounds like.
- def method_name
- r = ""
- scoped = false
- each_byte do |c|
- if c == 58
- if not scoped
- r << "_"
- scoped = true
+ return([start, i - start]) if cnt >= sz
else
- scoped = false
+ i += 1
end
- else
- if r.size == 0
- r << c.chr.downcase
+ end
+
+ return false, false
+ end
+
+ # A la Unix strings(1). With a block, yields offset, string length,
+ # and contents. Otherwise returns a list. Accepts options:
+ # :unicode: superficial but effective Win32 Unicode support, skips NULs
+ # :minimum: minimum length of returned strings, ala strings -10
+ def strings(opts={})
+ ret = []
+ opts[:offset] ||= 0
+ while 1
+ off, size = nextstring(opts)
+ break if not off
+ opts[:offset] += (off + size)
+ if block_given?
+ yield off, size, self[off,size]
else
- if c.upper?
+ ret << [off, size, self[off,size]]
+ end
+ end
+ ret
+ end
+
+ # A hacked up adler16 checksum, a la Andrew Tridgell. This is probably
+ # even slower than Ruby's native CRC support. A weak, trivial checksum,
+ # part of rsync.
+ def adler
+ a, b = 0, 0
+ 0.upto(size-1) {|i| a += self[i]}
+ a %= 65536
+ 0.upto(size-1) {|i| b += ((size-i)+1) * self[i]}
+ b %= 65536
+ return (a|(b<<16))
+ end
+
+ # Convert binary strings back to integers
+ def to_l32; unpack("L").first; end
+ def to_b32; unpack("N").first; end
+ def to_l16; unpack("v").first; end
+ def to_b16; unpack("n").first; end
+ def to_u8; self[0]; end
+ def shift_l32; shift(4).to_l32; end
+ def shift_b32; shift(4).to_b32; end
+ def shift_l16; shift(2).to_l16; end
+ def shift_b16; shift(2).to_b16; end
+ def shift_u8; shift(1).to_u8; end
+
+ # oh, it's exactly what it sounds like.
+ def method_name
+ r = ""
+ scoped = false
+ each_byte do |c|
+ if c == 58
+ if not scoped
r << "_"
+ scoped = true
+ else
+ scoped = false
+ end
+ else
+ if r.size == 0
r << c.chr.downcase
else
- r << c.chr
+ if c.upper?
+ r << "_"
+ r << c.chr.downcase
+ else
+ r << c.chr
+ end
end
end
end
+ return r
end
- return r
- end
- # I love you String#ljust
- def pad(size, char="\x00")
- ljust(size, char)
- end
+ # I love you String#ljust
+ def pad(size, char="\x00")
+ ljust(size, char)
+ end
- # Convert a string into hex characters
- def hexify
- l = []
- each_byte{|b| l << "%02x" % b}
- l.join
- end
+ # Convert a string into hex characters
+ def hexify
+ l = []
+ each_byte{|b| l << "%02x" % b}
+ l.join
+ end
- # convert a string to hex characters in place
- def hexify!
- self.replace hexify
- end
+ # convert a string to hex characters in place
+ def hexify!
+ self.replace hexify
+ end
- # Convert a string of raw hex characters (no %'s or anything) into binary
- def dehexify
- (ret||="") << (me||=clone).shift(2).to_i(16).chr while not (me||=clone).empty?
- return ret
- end
+ # Convert a string of raw hex characters (no %'s or anything) into binary
+ def dehexify
+ (ret||="") << (me||=clone).shift(2).to_i(16).chr while not (me||=clone).empty?
+ return ret
+ end
- # Convert a string of raw hex characters (no %'s or anything) into binary in place
- def dehexify!
- (ret||="") << (me||=clone).shift(2).to_i(16).chr while not (me||=clone).empty?
- self.replace ret
- end
+ # Convert a string of raw hex characters (no %'s or anything) into binary in place
+ def dehexify!
+ (ret||="") << (me||=clone).shift(2).to_i(16).chr while not (me||=clone).empty?
+ self.replace ret
+ end
+
+ # OR two strings together. Slow. Handles mismatched lengths by zero-extending
+ def or(str)
+ max = size < str.size ? str.size : size
+ ret = ""
+ 0.upto(max-1) do |i|
+ x = self[i] || 0
+ y = str[i] || 0
+ ret << (x | y).chr
+ end
+ return ret
+ end
- # OR two strings together. Slow. Handles mismatched lengths by zero-extending
- def or(str)
- max = size < str.size ? str.size : size
- ret = ""
- 0.upto(max-1) do |i|
- x = self[i] || 0
- y = str[i] || 0
- ret << (x | y).chr
+ # XOR two strings. wrapping around if str is shorter thn self.
+ def xor(str)
+ r = []
+ size.times do |i|
+ r << (self[i] ^ str[i % str.size]).chr
+ end
+ return r.join
end
- return ret
- end
-
- # XOR two strings. wrapping around if str is shorter thn self.
- def xor(str)
- r = []
- size.times do |i|
- r << (self[i] ^ str[i % str.size]).chr
- end
- return r.join
- end
-
- def xor!(str)
- size.times do |i|
- self[i] ^= str[i % str.size]
- end
- end
-
- # byte rotation cypher (yes it's been useful)
- def rotate_bytes(k=0)
- r = []
- each_byte do |b|
- r << ((b + k) % 256).chr
- end
- return r.join
- end
-
- # Insanely useful shorthand: pop bytes off the front of a string
- def shift(count=1)
- return self if count == 0
- slice! 0..(count-1)
- end
- def underscore
- first = false
- gsub(/[a-z0-9][A-Z]/) do |m|
- "#{ m[0].chr }_#{ m[1].chr.downcase }"
+ def xor!(str)
+ size.times do |i|
+ self[i] ^= str[i % str.size]
+ end
end
- end
- # "foo: bar".shift_tok /:\s*/ => "foo" # leaving "bar"
- def shift_tok(rx)
- src = rx.source if rx.kind_of? Regexp
- rx = Regexp.new "(#{ src })"
- idx = (self =~ rx)
- if idx
- ret = shift(idx)
- shift($1.size)
- return ret
- else
- shift(self.size)
+ # byte rotation cypher (yes it's been useful)
+ def rotate_bytes(k=0)
+ r = []
+ each_byte do |b|
+ r << ((b + k) % 256).chr
+ end
+ return r.join
+ end
+
+ # Insanely useful shorthand: pop bytes off the front of a string
+ def shift(count=1)
+ return self if count == 0
+ slice! 0..(count-1)
+ end
+
+ def underscore
+ first = false
+ gsub(/[a-z0-9][A-Z]/) do |m|
+ "#{ m[0].chr }_#{ m[1].chr.downcase }"
+ end
+ end
+
+ # "foo: bar".shift_tok /:\s*/ => "foo" # leaving "bar"
+ def shift_tok(rx)
+ src = rx.source if rx.kind_of? Regexp
+ rx = Regexp.new "(#{ src })"
+ idx = (self =~ rx)
+ if idx
+ ret = shift(idx)
+ shift($1.size)
+ return ret
+ else
+ shift(self.size)
+ end
end
end
+ include StringExtensions
end
View
4 ruckus/number.rb
@@ -347,4 +347,8 @@ def initialize(opts={})
end
end
+ class Decimal < Ruckus::Number
+ OPTIONS = { :ascii => true, :radix => 10 }
+ end
+
end
View
6 ruckus/str.rb
@@ -1,5 +1,11 @@
# === Pretty much anything that isn't a Number is a Str
+# class Symbol
+# def clone
+# self # fuck you ruby, what the fuck is wrong with you
+# end
+# end
+
module Ruckus
# A Ruckus::Str is a bag of bytes, wrapping a Ruby string
class Str < Parsel
View
41 ruckus/structure.rb
@@ -36,15 +36,27 @@ class Structure < Parsel
# 5. Call #new on it (when the object is instantiated)
#
def method_missing(meth, *args)
+ if meth.to_s =~ /^relate_(.*)/
+ return relate($1.intern, *args)
+ end
+
if not args[-1].kind_of? Hash or not (mod = args[-1][:from])
mod = Ruckus
end
- if args[0] and args[1] and args[0].kind_of? Symbol
- args[1][:name] = args[0]
+ if args[0] and args[0].kind_of? Symbol
+ if args[1]
+ args[1][:name] = args[0]
+ else
+ args[1] = { :name => args[0] }
+ end
args.shift
end
+ if [ "value", "name", "size" ].include?(nm = args[0][:name] && args[0][:name].to_s) or (nm and nm.starts_with? "relate_")
+ raise "can't have fields named #{ nm }, because we suck; rename the field"
+ end
+
begin
klass = mod.const_get(meth.to_s.class_name)
rescue
@@ -54,6 +66,29 @@ def method_missing(meth, *args)
add(klass, *args)
end
+
+ def relate(attr, field, opts={})
+ opts[:through] ||= :value
+ raise "need a valid field to relate" if not field
+ raise "need :to argument" if not opts[:to]
+
+ @@initializers[self] << lambda do
+ f = send(field)
+
+ case attr
+ when :value
+ f.value = opts[:through]
+ f.instance_eval { @from_field = opts[:to] }
+ when :size
+ f.instance_eval {
+ @in_size = {
+ :meth => opts[:through],
+ :from_field => opts[:to]
+ }
+ }
+ end
+ end
+ end
}
# holy crap I need to figure this metaclass stuff out
@@ -230,6 +265,8 @@ def method_missing(meth, *args)
setter = (m[-1].chr == "=") ? true : false
m = m[0..-2] if setter
+ puts "WARNING: assignment to @value as struct field" if setter and m == "value"
+
if (i = d[m.intern])
if setter
self[m.intern] = args[0]
Please sign in to comment.
Something went wrong with that request. Please try again.