Class BytecodeConverter
In: lib/swxruby/bytecode_converter.rb
Parent: Object

Methods

Included Modules

HelperMethods

Constants

NULL_TERMINATOR = '00'

External Aliases

complex_data_structure_to_bytecode -> array_to_bytecode
complex_data_structure_to_bytecode -> hash_to_bytecode
integer_to_bytecode -> bignum_to_bytecode
integer_to_bytecode -> fixnum_to_bytecode

Public Class methods

[Source]

    # File lib/swxruby/bytecode_converter.rb, line 10
10:           def convert(data)
11:             conversion_method = "#{data.class.to_s.downcase}_to_bytecode"
12:             
13:             if respond_to?(conversion_method)
14:               send(conversion_method, data)
15:             else
16:                                 # Convert the object to a hash of its instance variables 
17:                                 object_hash = data.instance_values
18:                                 
19:                                 if object_hash.empty?
20:                                         raise StandardError, "#{data.class} is an unhandled data type."
21:                                 else
22:                       hash_to_bytecode(object_hash)
23:                                 end
24:             end
25:           end

Protected Class methods

Data Type Conversion Methods

[Source]

    # File lib/swxruby/bytecode_converter.rb, line 29
29:                 def complex_data_structure_to_bytecode(data) #:nodoc#
30:                         bytecode = []
31:                         
32:                         # Keeps track of bytecode when recursing into nested data structures
33:                         stack = []
34: 
35:                         # Add the bytecode to initialize the data structure
36:                         bytecode.push(data.is_a?(Array) ? ActionCodes::INIT_ARRAY : ActionCodes::INIT_OBJECT)
37: 
38:                         # Add the length of the data structure to the bytecode
39:                         bytecode.push integer_to_bytecode(data.length)
40:                         
41:                         # Convert each element in the data structure to bytecode
42:                         data.each do |element|
43:                                 
44:         # assume we're not iterating into a recursive data structure
45:         complex_data_structure = false
46:         
47:                                 # if we're converting a hash, then convert the hash's value
48:                                 if data.is_a?(Hash)
49:                                 value_bytecode = convert(element[1]) 
50:                                 # if we just converted an array or a hash, set complex_data_structure to true
51:                                 complex_data_structure = true if value_bytecode.concludes_with?(ActionCodes::INIT_OBJECT, ActionCodes::INIT_ARRAY)
52:                                 # set the element local variable to the key of the hash
53:                                         element = element[0]
54:                                 end
55:                                 
56:                                 # element will always contain something (whether iterating over a hash or an array)
57:                                 element_bytecode = convert(element)
58:                                 # if we just converted an array or a hash, set complex_data_structure to true
59:                                 complex_data_structure = true if element_bytecode.concludes_with?(ActionCodes::INIT_OBJECT, ActionCodes::INIT_ARRAY)
60: 
61:         # Create a push of the current bytecode, if
62:                                          # we recursed into a complex data structure
63:                                          #                                                                                  or we're approaching the 65535 byte limit that can be stored in a single push. 
64:         if (complex_data_structure || calculate_bytecode_length(bytecode) > 65518)
65:         
66:           # If we haven't written any bytecode into the local
67:           # buffer yet (if it's empty), or all the data is already pushed, skip writing the push statement
68:           bytecode.push generate_push_statement(bytecode) unless bytecode.empty? || bytecode.last.begins_with?('96')
69:           
70:           # Store current instruction on the stack (SWF bytecode is stored in reverse, so we reverse it here)
71:           stack.push bytecode.reverse.join
72:           
73:           # Reset the bytecode
74:           bytecode = []
75:         end
76:         
77:         # value_bytecode will be nil unless we converted a Hash
78:                                 bytecode.push value_bytecode unless value_bytecode.nil?
79: 
80:                                 bytecode.push element_bytecode
81:                         end
82: 
83:       # If we haven't written any bytecode into the local
84:                         # buffer yet (if it's empty), or all the data is already pushed, skip writing the push statement
85:       bytecode.push generate_push_statement(bytecode) unless bytecode.empty? || bytecode.last.begins_with?('96')
86:                         
87:                         # Add the bytecode to the local stack variable (SWF bytecode is stored in reverse, so we reverse it here)
88:                         stack.push bytecode.reverse.join
89:                         
90:                         # Join the stack array into a string and return it (SWF bytecode is stored in reverse, so we reverse it here)
91:                         stack.reverse.join
92:                 end

[Source]

    # File lib/swxruby/bytecode_converter.rb, line 96
96:     def date_to_bytecode(date) #:nodoc#
97:       # Format: 2006-09-14
98:       string_to_bytecode(date.strftime('%Y-%m-%d'))
99:     end

[Source]

     # File lib/swxruby/bytecode_converter.rb, line 101
101:     def datetime_to_bytecode(datetime) #:nodoc#
102:       # Format: 2006-09-14 02:21:10
103:                         string_to_bytecode(datetime.strftime('%Y-%m-%d %I:%M:%S'))
104:     end

[Source]

     # File lib/swxruby/bytecode_converter.rb, line 106
106:     def falseclass_to_bytecode(*args) #:nodoc#
107:       DataTypeCodes::BOOLEAN + '00'
108:     end

[Source]

     # File lib/swxruby/bytecode_converter.rb, line 110
110:                 def float_to_bytecode(float) #:nodoc#
111:                         hex = []
112:                         [float].pack('E').each_byte { |byte| hex << '%02X' % byte }
113:                                                                                                                         # Aral did this in SWX PHP, so I'm doing it here
114:                         DataTypeCodes::FLOAT + (hex[4..-1] + hex[0..3]).join
115:                 end

[Source]

     # File lib/swxruby/bytecode_converter.rb, line 117
117:                 def integer_to_bytecode(integer) #:nodoc#
118:                         DataTypeCodes::INTEGER + integer_to_hexadecimal(integer, 4)
119:                 end

[Source]

     # File lib/swxruby/bytecode_converter.rb, line 123
123:                 def nilclass_to_bytecode(*args) #:nodoc#
124:                   '02'
125:                 end

[Source]

     # File lib/swxruby/bytecode_converter.rb, line 127
127:                 def string_to_bytecode(string) #:nodoc#
128:             DataTypeCodes::STRING + string.unpack('H*').join.upcase + NULL_TERMINATOR
129:           end

[Source]

     # File lib/swxruby/bytecode_converter.rb, line 131
131:     def symbol_to_bytecode(symbol)
132:       string_to_bytecode(symbol.to_s)
133:     end

[Source]

     # File lib/swxruby/bytecode_converter.rb, line 135
135:           def trueclass_to_bytecode(*args) #:nodoc#
136:       DataTypeCodes::BOOLEAN + '01'
137:           end

[Validate]