| Class | BytecodeConverter |
| In: |
lib/swxruby/bytecode_converter.rb
|
| Parent: | Object |
| NULL_TERMINATOR | = | '00' |
| 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 |
# 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
# 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
# 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
# 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
# File lib/swxruby/bytecode_converter.rb, line 106
106: def falseclass_to_bytecode(*args) #:nodoc#
107: DataTypeCodes::BOOLEAN + '00'
108: end
# 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
# 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
# File lib/swxruby/bytecode_converter.rb, line 123
123: def nilclass_to_bytecode(*args) #:nodoc#
124: '02'
125: end
# 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
# File lib/swxruby/bytecode_converter.rb, line 131
131: def symbol_to_bytecode(symbol)
132: string_to_bytecode(symbol.to_s)
133: end