ruckus 0.5.4

Sign up to get free protection for your applications and to get access to all the features.
Files changed (59) hide show
  1. data/.document +5 -0
  2. data/.gitignore +22 -0
  3. data/README +0 -0
  4. data/README.markdown +51 -0
  5. data/Rakefile +54 -0
  6. data/VERSION +1 -0
  7. data/lib/ruckus.rb +70 -0
  8. data/lib/ruckus/blob.rb +113 -0
  9. data/lib/ruckus/choice.rb +55 -0
  10. data/lib/ruckus/dfuzz.rb +231 -0
  11. data/lib/ruckus/dictionary.rb +119 -0
  12. data/lib/ruckus/enum.rb +39 -0
  13. data/lib/ruckus/extensions/array.rb +33 -0
  14. data/lib/ruckus/extensions/class.rb +168 -0
  15. data/lib/ruckus/extensions/duplicable.rb +37 -0
  16. data/lib/ruckus/extensions/file.rb +24 -0
  17. data/lib/ruckus/extensions/fixnum.rb +26 -0
  18. data/lib/ruckus/extensions/hash.rb +10 -0
  19. data/lib/ruckus/extensions/integer.rb +26 -0
  20. data/lib/ruckus/extensions/ipaddr.rb +155 -0
  21. data/lib/ruckus/extensions/irb.rb +30 -0
  22. data/lib/ruckus/extensions/math.rb +6 -0
  23. data/lib/ruckus/extensions/module.rb +37 -0
  24. data/lib/ruckus/extensions/numeric.rb +117 -0
  25. data/lib/ruckus/extensions/object.rb +22 -0
  26. data/lib/ruckus/extensions/range.rb +16 -0
  27. data/lib/ruckus/extensions/socket.rb +20 -0
  28. data/lib/ruckus/extensions/string.rb +327 -0
  29. data/lib/ruckus/filter.rb +16 -0
  30. data/lib/ruckus/human_display.rb +79 -0
  31. data/lib/ruckus/ip.rb +38 -0
  32. data/lib/ruckus/mac_addr.rb +31 -0
  33. data/lib/ruckus/mutator.rb +318 -0
  34. data/lib/ruckus/null.rb +24 -0
  35. data/lib/ruckus/number.rb +360 -0
  36. data/lib/ruckus/parsel.rb +363 -0
  37. data/lib/ruckus/selector.rb +92 -0
  38. data/lib/ruckus/str.rb +164 -0
  39. data/lib/ruckus/structure.rb +263 -0
  40. data/lib/ruckus/structure/atcreate.rb +23 -0
  41. data/lib/ruckus/structure/beforebacks.rb +28 -0
  42. data/lib/ruckus/structure/defaults.rb +57 -0
  43. data/lib/ruckus/structure/factory.rb +42 -0
  44. data/lib/ruckus/structure/fixupfields.rb +16 -0
  45. data/lib/ruckus/structure/initializers.rb +14 -0
  46. data/lib/ruckus/structure/relate.rb +34 -0
  47. data/lib/ruckus/structure/replacement.rb +30 -0
  48. data/lib/ruckus/structure/searchmods.rb +33 -0
  49. data/lib/ruckus/structure/structureproxies.rb +28 -0
  50. data/lib/ruckus/structure/validate.rb +12 -0
  51. data/lib/ruckus/structure_shortcuts.rb +109 -0
  52. data/lib/ruckus/time_t.rb +26 -0
  53. data/lib/ruckus/vector.rb +97 -0
  54. data/ruckus.gemspec +104 -0
  55. data/test/test_decides.rb +61 -0
  56. data/test/test_mutator.rb +29 -0
  57. data/test/test_override.rb +23 -0
  58. data/test/test_replace.rb +39 -0
  59. metadata +138 -0
@@ -0,0 +1,119 @@
1
+ # === A collection of objects of which only one is active at any particular time
2
+
3
+ module Ruckus
4
+ # A Dictionary is a collection of data objects of which only one is
5
+ # active at any particular time. This class extends and provies a simplified
6
+ # front-end for Choice.
7
+ #
8
+ class Dictionary < Choice
9
+ attr_accessor :dict, :selection
10
+
11
+ # Initializes a new Dictionary object.
12
+ # Parameters may be provided at initialisation to control the behaviour
13
+ # of an object. These params are:
14
+ #
15
+ # dict An indexable (generally hash or array) object with indexed
16
+ # values mapped to the possible data objects. (see notes below)
17
+ # Any indexable object using the [] method can be used,
18
+ # provided that 'selection' returns a valid index. If a type
19
+ # is to have parameters passed to it, then it should be
20
+ # provided as [type, hash_params]
21
+ #
22
+ # selection An index into :dict which specifies the currently
23
+ # active choice.
24
+ #
25
+ # default An optional parameter specifying the default class
26
+ # to capture to.
27
+ #
28
+ # A selection may be any of the following:
29
+ #
30
+ # - Immediate Value:
31
+ # An immediate value to be used as the index. Fixnum
32
+ #
33
+ # - Symbol:
34
+ # A symbol which will be will be searched with 'find_tag' from the
35
+ # root of the parent structure. The value of the tagged element is used
36
+ # as the index.
37
+ # - By default a type symbol will be converted to an immediate name and
38
+ # pulled from the Ruckus namespace.
39
+ # - To specify another namespace, use the :dict_from parameter as in
40
+ # ":dict_from => Name::Space". A :dict_from namespace can be
41
+ # set globally or overidden as a per choice parameter.
42
+ #
43
+ # - Proc/Lambda:
44
+ # The lambda or proc is called and passed the following parameters:
45
+ #
46
+ # 'buf' - The capture buffer
47
+ # 'this' - A reference to the current choice structure.
48
+ #
49
+ # The lambda must return either of the following
50
+ #
51
+ # An immediate value for the index to select
52
+ #
53
+ # An array pair consisting of the immediate value and sub-string
54
+ # buffer for the selection.
55
+ #
56
+ # NOTE: The latter form allows the proc to perform its own internal
57
+ # 'captures'. The proc is expected to remove (slice!) any contents
58
+ # from the original buffer for whatever extractions are made with
59
+ # 'capture'.
60
+ #
61
+ def initialize(opts={})
62
+ @dict = (opts[:dict] || [])
63
+ @selection = (opts[:selection] || nil)
64
+ @dict_from = (opts[:dict_from] || Ruckus)
65
+ @default = opts[:default]
66
+
67
+ # This lambda is passed to the 'choice' superclass to provide
68
+ # all the dictionary functionality.
69
+ block = lambda do |buf, this|
70
+ lambuf = nil
71
+ case @selection
72
+ when Symbol
73
+ sel = (x=this.root.find_tag(@selection) and x.value)
74
+ when Proc
75
+ sel, lambuf = @selection.call(buf,this)
76
+ else
77
+ sel = @selection
78
+ end
79
+
80
+ if (k = @dict[sel]) or (k = @default)
81
+ ksym, *args = k
82
+ return buf unless ksym
83
+
84
+ unless args[-1].kind_of?(Hash) and nsp=args[-1][:dict_from]
85
+ nsp = @dict_from
86
+ end
87
+
88
+ klass = if (ksym.kind_of? Class or ksym.kind_of? Module)
89
+ ksym
90
+ else
91
+ ksym.to_s.const_lookup(nsp) or return(buf)
92
+ end
93
+
94
+ choice = klass.new(*args)
95
+ choice.parent = this.value.parent
96
+ this.value = choice
97
+
98
+ if not lambuf.nil?
99
+ return buf if x=this.value.capture(lambuf) and x.empty?
100
+ else
101
+ this.value.capture(buf)
102
+ end
103
+ end
104
+ end
105
+
106
+ super( opts.merge(:block => block) )
107
+ end
108
+
109
+ end # class Dictionary
110
+
111
+ class Structure
112
+ # Convenience alias for 'dictionary'. First arg is "name", all others
113
+ # are passed directly into 'new'
114
+ def self.dict(*args)
115
+ with_args(*args) {|name, opts| dictionary opts.merge(:name => name)}
116
+ end
117
+ end
118
+
119
+ end # module Ruckus
@@ -0,0 +1,39 @@
1
+
2
+ module Ruckus
3
+ class Enum < Number
4
+ attr_accessor :enums
5
+
6
+ def initialize(opts={})
7
+ super(opts)
8
+ @enums ||= []
9
+ raise "enums must be Enumerable" unless @enums.kind_of? Enumerable
10
+ end
11
+
12
+ def to_human(indent="")
13
+ "#{indent}#{@name} = #{@value}(#{@value.to_hex}) [ #{ ((n=lookup)? n : "???").to_s } ]"
14
+ end
15
+
16
+ def lookup
17
+ if (o=@enums[@value]).kind_of?(Hash) then o[:name] else o end
18
+ end
19
+ end
20
+
21
+ class Structure
22
+ def self.enum16le(*args)
23
+ with_args(*args) {|name, opts| enum name, opts.merge(:width => 16, :endian => :little)}
24
+ end
25
+
26
+ def self.enum32le(*args)
27
+ with_args(*args) {|name, opts| enum name, opts.merge(:width => 32, :endian => :little)}
28
+ end
29
+
30
+ def self.enum16be(*args)
31
+ with_args(*args) {|name, opts| enum name, opts.merge(:width => 16, :endian => :big)}
32
+ end
33
+
34
+ def self.enum32be(*args)
35
+ with_args(*args) {|name, opts| enum name, opts.merge(:width => 32, :endian => :big)}
36
+ end
37
+ end
38
+ end
39
+
@@ -0,0 +1,33 @@
1
+ class Array
2
+ module ArrayExtensions
3
+ # Assume an array of key, value tuples, and convert to Hash
4
+ def to_hash
5
+ r = {}
6
+ each {|it| r[it[0]] = it[1]}
7
+ return r
8
+ end
9
+
10
+ def kind_of_these? y
11
+ inject(false) {|acc, klass| acc || y.kind_of?(klass)}
12
+ end
13
+
14
+ #return first hash-like element with key k
15
+ def kassoc(k)
16
+ # XXX not used
17
+ each { |h| return h if h.try(:has_key?, k) }
18
+ return nil
19
+ end
20
+
21
+ #return first hash-like element with value v
22
+ def vassoc(v)
23
+ # XXX not used
24
+ each { |h| return h if h.try(:has_value?, v) }
25
+ return nil
26
+ end
27
+
28
+ def extract_options!
29
+ last.is_a?(::Hash) ? pop : {}
30
+ end
31
+ end
32
+ include ArrayExtensions
33
+ end
@@ -0,0 +1,168 @@
1
+ class Class
2
+ module ClassExtensions
3
+ # Also crazy that this isn't in the library
4
+ def inherits_from?(klass)
5
+ return true if self == klass
6
+ return true if self.superclass == klass
7
+ return false if self.superclass == Object
8
+
9
+ rec = lambda do |x|
10
+ if x == Object
11
+ false
12
+ elsif x == klass
13
+ true
14
+ else
15
+ rec.call(x.superclass)
16
+ end
17
+ end
18
+
19
+ rec.call(self)
20
+ end
21
+
22
+ def alias_cmethod(to, from)
23
+ # XXX not used
24
+ (class << self;self;end).class_eval {
25
+ define_method to do |*args|
26
+ send(from, *args)
27
+ end
28
+ }
29
+ end
30
+
31
+
32
+ # Allows attributes to be shared within an inheritance hierarchy, but where each descendant gets a copy of
33
+ # their parents' attributes, instead of just a pointer to the same. This means that the child can add elements
34
+ # to, for example, an array without those additions being shared with either their parent, siblings, or
35
+ # children, which is unlike the regular class-level attributes that are shared across the entire hierarchy.
36
+ def class_inheritable_reader(*syms)
37
+ syms.each do |sym|
38
+ next if sym.is_a?(Hash)
39
+ class_eval <<-EOS
40
+ def self.#{sym}
41
+ read_inheritable_attribute(:#{sym})
42
+ end
43
+
44
+ def #{sym}
45
+ self.class.#{sym}
46
+ end
47
+ EOS
48
+ end
49
+ end
50
+
51
+ def class_inheritable_writer(*syms)
52
+ options = syms.extract_options!
53
+ syms.each do |sym|
54
+ class_eval <<-EOS
55
+ def self.#{sym}=(obj)
56
+ write_inheritable_attribute(:#{sym}, obj)
57
+ end
58
+
59
+ #{"
60
+ def #{sym}=(obj)
61
+ self.class.#{sym} = obj
62
+ end
63
+ " unless options[:instance_writer] == false }
64
+ EOS
65
+ end
66
+ end
67
+
68
+ def class_inheritable_array_writer(*syms)
69
+ options = syms.extract_options!
70
+ syms.each do |sym|
71
+ class_eval <<-EOS
72
+ def self.#{sym}=(obj)
73
+ write_inheritable_array(:#{sym}, obj)
74
+ end
75
+
76
+ #{"
77
+ def #{sym}=(obj)
78
+ self.class.#{sym} = obj
79
+ end
80
+ " unless options[:instance_writer] == false }
81
+ EOS
82
+ end
83
+ end
84
+
85
+ def class_inheritable_hash_writer(*syms)
86
+ options = syms.extract_options!
87
+ syms.each do |sym|
88
+ class_eval <<-EOS
89
+ def self.#{sym}=(obj)
90
+ write_inheritable_hash(:#{sym}, obj)
91
+ end
92
+
93
+ #{"
94
+ def #{sym}=(obj)
95
+ self.class.#{sym} = obj
96
+ end
97
+ " unless options[:instance_writer] == false }
98
+ EOS
99
+ end
100
+ end
101
+
102
+ def class_inheritable_accessor(*syms)
103
+ class_inheritable_reader(*syms)
104
+ class_inheritable_writer(*syms)
105
+ end
106
+
107
+ def class_inheritable_array(*syms)
108
+ class_inheritable_reader(*syms)
109
+ class_inheritable_array_writer(*syms)
110
+ end
111
+
112
+ def class_inheritable_hash(*syms)
113
+ class_inheritable_reader(*syms)
114
+ class_inheritable_hash_writer(*syms)
115
+ end
116
+
117
+ def inheritable_attributes
118
+ @inheritable_attributes ||= EMPTY_INHERITABLE_ATTRIBUTES
119
+ end
120
+
121
+ def write_inheritable_attribute(key, value)
122
+ if inheritable_attributes.equal?(EMPTY_INHERITABLE_ATTRIBUTES)
123
+ @inheritable_attributes = {}
124
+ end
125
+ inheritable_attributes[key] = value
126
+ end
127
+
128
+ def write_inheritable_array(key, elements)
129
+ write_inheritable_attribute(key, []) if read_inheritable_attribute(key).nil?
130
+ write_inheritable_attribute(key, read_inheritable_attribute(key) + elements)
131
+ end
132
+
133
+ def write_inheritable_hash(key, hash)
134
+ write_inheritable_attribute(key, {}) if read_inheritable_attribute(key).nil?
135
+ write_inheritable_attribute(key, read_inheritable_attribute(key).merge(hash))
136
+ end
137
+
138
+ def read_inheritable_attribute(key)
139
+ inheritable_attributes[key]
140
+ end
141
+
142
+ def reset_inheritable_attributes
143
+ @inheritable_attributes = EMPTY_INHERITABLE_ATTRIBUTES
144
+ end
145
+ private
146
+
147
+ # Prevent this constant from being created multiple times
148
+ EMPTY_INHERITABLE_ATTRIBUTES = {}.freeze unless const_defined?(:EMPTY_INHERITABLE_ATTRIBUTES)
149
+
150
+ def inherited_with_inheritable_attributes(child)
151
+ inherited_without_inheritable_attributes(child) if respond_to?(:inherited_without_inheritable_attributes)
152
+
153
+ if inheritable_attributes.equal?(EMPTY_INHERITABLE_ATTRIBUTES)
154
+ new_inheritable_attributes = EMPTY_INHERITABLE_ATTRIBUTES
155
+ else
156
+ new_inheritable_attributes = inheritable_attributes.inject({}) do |memo, (key, value)|
157
+ memo.update(key => value.duplicable? ? value.dup : value)
158
+ end
159
+ end
160
+
161
+ child.instance_variable_set('@inheritable_attributes', new_inheritable_attributes)
162
+ end
163
+ end
164
+
165
+ include ClassExtensions
166
+ alias inherited_without_inheritable_attributes inherited
167
+ alias inherited inherited_with_inheritable_attributes
168
+ end
@@ -0,0 +1,37 @@
1
+ class Object
2
+ # Can you safely .dup this object?
3
+ # False for nil, false, true, symbols, and numbers; true otherwise.
4
+ def duplicable?
5
+ true
6
+ end
7
+ end
8
+
9
+ class NilClass #:nodoc:
10
+ def duplicable?
11
+ false
12
+ end
13
+ end
14
+
15
+ class FalseClass #:nodoc:
16
+ def duplicable?
17
+ false
18
+ end
19
+ end
20
+
21
+ class TrueClass #:nodoc:
22
+ def duplicable?
23
+ false
24
+ end
25
+ end
26
+
27
+ class Symbol #:nodoc:
28
+ def duplicable?
29
+ false
30
+ end
31
+ end
32
+
33
+ class Numeric #:nodoc:
34
+ def duplicable?
35
+ false
36
+ end
37
+ end
@@ -0,0 +1,24 @@
1
+ class File
2
+ module FileExtensions
3
+ module ClassMethods
4
+ def mkfifo(name, mode="666", open_mode="r")
5
+ # XXX not used
6
+ if File.exists? name and File.pipe? name # Leftover from before
7
+ File.delete name
8
+ end
9
+
10
+ # apalling, but ruby/dl has x-p problems
11
+ if ! File.exists? name
12
+ `mkfifo -m #{ mode } #{ name }`
13
+ end
14
+
15
+ return File.open(name, open_mode)
16
+ end
17
+ end
18
+
19
+ def self.included(klass)
20
+ klass.extend(ClassMethods)
21
+ end
22
+ end
23
+ include FileExtensions
24
+ end
@@ -0,0 +1,26 @@
1
+ class Fixnum
2
+ module FixnumExtensions
3
+ # Ridiculous that this isn't in the library.
4
+ def printable?; self >= 0x20 and self <= 0x7e; end
5
+
6
+ # Like Numeric#Step, but yields the length of each span along with
7
+ # the offset. Useful for stepping through data in increments:
8
+ # 0.stepwith(buffer.size, 4096) {|off,len| pp buffer[off,len]}
9
+ # The "len" parameter accounts for the inevitable short final block.
10
+ def stepwith(limit, stepv, &block)
11
+ # XXX not used
12
+ step(limit, stepv) do |i|
13
+ remt = limit - i
14
+ yield i, remt.cap(stepv)
15
+ end
16
+ end
17
+
18
+ # you can't clone a fixnum? Why?
19
+ def clone; self; end
20
+
21
+ def upper?; self >= 0x41 and self <= 0x5a; end
22
+ def lower?; self >= 0x61 and self <= 0x7a; end
23
+ end
24
+ include FixnumExtensions
25
+ end
26
+