Class: StructFx
- Inherits:
-
Object
- Object
- StructFx
- Defined in:
- lib/struct-fx.rb
Overview
StructFx builder and analyzer.
Defined Under Namespace
Classes: Compiled
Constant Summary collapse
- TYPES =
Holds types metainformations map.
Frozen << { :int8 => ["c", 1], :int16 => ["s", 2], :int32 => ["l", 4], :int64 => ["q", 8], :uint8 => ["C", 1], :uint16 => ["S", 2], :uint32 => ["L", 4], :uint64 => ["Q", 8], :float => ["f", 4], :double => ["d", 8], :char => ["a", 1], :string => ["Z", 1], :byte => ["C", 1], :skip => ["a", 1], }
Instance Attribute Summary collapse
-
#raw ⇒ String
readonly
Holds raw data.
Instance Method Summary collapse
-
#<<(value) ⇒ Object
Fills by input data.
-
#add(name, type, callback = nil, block = nil) ⇒ Object
Adds declaration.
-
#byte(name, &block) ⇒ Object
Adds byte BitPacker declaration.
-
#bytesize ⇒ Integer
(also: #length)
Returns total length of the struct in bytes.
-
#compiled ⇒ Class
Returns compiled form.
-
#data ⇒ Class
Returns structure analyze.
-
#declare(&block) ⇒ Object
Receives declaration.
-
#initialize(data = nil, &block) ⇒ StructFx
constructor
Constructor.
-
#method_missing(name, *args, &block) ⇒ Integer
Handles missing methods as declarations.
-
#skip(&block) ⇒ Object
Adds skipping declaration.
-
#to_s ⇒ String
Converts to string.
Constructor Details
#initialize(data = nil, &block) ⇒ StructFx
Constructor.
83 84 85 86 87 88 89 90 |
# File 'lib/struct-fx.rb', line 83 def initialize(data = nil, &block) @stack = [ ] self.declare(&block) if not data.nil? self << data end end |
Dynamic Method Handling
This class handles dynamic methods through the method_missing method
#method_missing(name, *args, &block) ⇒ Integer
Handles missing methods as declarations.
137 138 139 140 141 142 143 |
# File 'lib/struct-fx.rb', line 137 def method_missing(name, *args, &block) if self.class::TYPES.include? name self.add(args.shift, name, nil, block) else raise Exception::new("Invalid type/method specified: '" << name.to_s << "'") end end |
Instance Attribute Details
#raw ⇒ String (readonly)
Holds raw data.
37 38 39 |
# File 'lib/struct-fx.rb', line 37 def raw @raw end |
Instance Method Details
#<<(value) ⇒ Object
Fills by input data.
204 205 206 207 208 209 210 211 |
# File 'lib/struct-fx.rb', line 204 def <<(value) if value.bytesize < self.compiled.length raise Exception::new("Data are shorter than declaration.") end @raw = value.to_s @data = nil end |
#add(name, type, callback = nil, block = nil) ⇒ Object
Adds declaration.
222 223 224 225 226 |
# File 'lib/struct-fx.rb', line 222 def add(name, type, callback = nil, block = nil) @stack << [name, type, callback, block] @struct = nil @compiled = nil end |
#byte(name, &block) ⇒ Object
Adds byte BitPacker declaration.
182 183 184 185 186 187 188 |
# File 'lib/struct-fx.rb', line 182 def byte(name, &block) callback = Proc::new do |value| BitPacker::new(value, &block) end self.add(name, :byte, callback) end |
#bytesize ⇒ Integer Also known as: length
Returns total length of the struct in bytes.
269 270 271 |
# File 'lib/struct-fx.rb', line 269 def bytesize self.compiled.length end |
#compiled ⇒ Class
Returns compiled form.
150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 |
# File 'lib/struct-fx.rb', line 150 def compiled if @compiled.nil? @compiled = self.class::Compiled::new([], [], "", "", [], 0) types = self.class::TYPES @stack.each do |name, type, args, block| = types[type] length = block.nil? ? 1 : block.call() pack_char = [0] + length.to_s total_length = [1] * length @compiled.enabled << (not name.nil?) @compiled.processors << args @compiled.packing << pack_char @compiled.unpacking << pack_char @compiled.lengths << total_length @compiled.length += total_length end end return @compiled end |
#data ⇒ Class
Returns structure analyze.
233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 |
# File 'lib/struct-fx.rb', line 233 def data if @data.nil? values = [ ] compiled = self.compiled extracted = @raw.unpack(compiled.unpacking) compiled.enabled.each_index do |i| # Skips skipped items if not compiled.enabled[i] next end # Calls postprocessing if required callback = compiled.processors[i] if callback.nil? values << extracted[i] else values << callback.call(extracted[i]) end end @data = __struct::new(*values) end return @data end |
#declare(&block) ⇒ Object
Receives declaration.
Adds declaration of bit array items. Can be call multiple times. New delcarations are joind to end of the array.
123 124 125 |
# File 'lib/struct-fx.rb', line 123 def declare(&block) self.instance_eval(&block) end |
#skip(&block) ⇒ Object
Adds skipping declaration.
195 196 197 |
# File 'lib/struct-fx.rb', line 195 def skip(&block) self.add(nil, :skip, nil, block) end |
#to_s ⇒ String
Converts to string.
280 281 282 283 284 285 286 287 288 289 290 291 292 293 294 295 296 297 298 299 300 301 302 303 304 305 306 |
# File 'lib/struct-fx.rb', line 280 def to_s entries = self.data.entries compiled = self.compiled values = [ ] length = 0 delta = 0 compiled.enabled.each_index do |i| # Pastes skipped data from RAW if not compiled.enabled[i] from = length to = (length + compiled.lengths[i]) values << @raw[from...to] delta += 1 # In otherwise, take value from analyzed data else values << entries[i - delta] # current item minus count of non-entry (skipped) items end length += self.compiled.lengths[i] end values.pack(self.compiled.packing) end |