divine 0.0.1 → 0.0.2
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- data/LICENSE.txt +2 -1
- data/Rakefile +49 -0
- data/lib/divine/code_generators/code_generator.rb +29 -6
- data/lib/divine/code_generators/java.rb +121 -14
- data/lib/divine/code_generators/javascript.rb +100 -11
- data/lib/divine/code_generators/ruby.rb +89 -4
- data/lib/divine/version.rb +1 -1
- data/test/basic_complex_test/basic_complex_test.rb +34 -0
- data/test/basic_complex_test/java_test/JavaTest.java +96 -0
- data/test/basic_complex_test/java_test/test_babel.java +368 -0
- data/test/basic_complex_test/js_test/js_testBasic.js +58 -0
- data/test/basic_complex_test/js_test/js_testComplex.js +68 -0
- data/test/basic_complex_test/js_test/test_babel.js +523 -0
- data/test/basic_complex_test/ruby_test/ruby_test.rb +68 -0
- data/test/basic_complex_test/ruby_test/test_babel.rb +368 -0
- data/test/binaryTree_test/binaryTree_test.rb +19 -0
- data/test/binaryTree_test/java_test/JavaTest.java +114 -0
- data/test/binaryTree_test/java_test/test_binaryTree.java +301 -0
- data/test/binaryTree_test/js_test/js_test.js +76 -0
- data/test/binaryTree_test/js_test/test_binaryTree.js +447 -0
- data/test/binaryTree_test/ruby_test/ruby_test.rb +68 -0
- data/test/binaryTree_test/ruby_test/test_binaryTree.rb +303 -0
- data/test/complex_test/complex_test.rb +23 -0
- data/test/complex_test/java_test/JavaTest.java +126 -0
- data/test/complex_test/java_test/test_complex.java +331 -0
- data/test/complex_test/js_test/js_test.js +69 -0
- data/test/complex_test/js_test/test_complex.js +478 -0
- data/test/complex_test/ruby_test/ruby_test.rb +55 -0
- data/test/complex_test/ruby_test/test_complex.rb +330 -0
- data/test/ipv6_test/ipv6_test.rb +14 -0
- data/test/ipv6_test/java_test/JavaTest.java +77 -0
- data/test/ipv6_test/java_test/junit.jar +0 -0
- data/test/ipv6_test/java_test/test_ipv6.java +270 -0
- data/test/ipv6_test/js_test/js_test.js +60 -0
- data/test/ipv6_test/js_test/test_ipv6.js +409 -0
- data/test/ipv6_test/ruby_test/ruby_test.rb +42 -0
- data/test/ipv6_test/ruby_test/test_ipv6.rb +267 -0
- data/test/java_lib/junit.jar +0 -0
- data/test/unify_test/java_test/test_unify.java +171 -0
- data/test/unify_test/js_test/js_test.js +56 -0
- data/test/unify_test/js_test/test_unify.js +326 -0
- data/test/unify_test/ruby_test/ruby_test.rb +35 -0
- data/test/unify_test/ruby_test/test_unify.rb +187 -0
- data/test/unify_test/unify_test.rb +17 -0
- metadata +77 -3
@@ -46,19 +46,47 @@ module Divine
|
|
46
46
|
end
|
47
47
|
|
48
48
|
def read_ip_number(data)
|
49
|
-
read_short_binary(data)
|
49
|
+
ips = read_short_binary(data)
|
50
|
+
if ips.size == 4
|
51
|
+
read_ipv4_number(ips)
|
52
|
+
else
|
53
|
+
read_ipv6_number(ips)
|
54
|
+
end
|
50
55
|
end
|
51
56
|
|
57
|
+
def read_ipv4_number(ips)
|
58
|
+
ips.bytes.to_a.join('.')
|
59
|
+
end
|
60
|
+
|
61
|
+
def read_ipv6_number(ips)
|
62
|
+
ipv6 = []
|
63
|
+
ips.bytes.each_slice(2) do |t|
|
64
|
+
fst = t[0]
|
65
|
+
lst = t[1]
|
66
|
+
tmp = ""
|
67
|
+
tmp = fst.to_s 16 if fst != 0
|
68
|
+
if fst != 0 and lst < 10
|
69
|
+
tmp << "0#{lst.to_s 16}"
|
70
|
+
elsif fst != 0 and lst > 10 or fst == 0 and lst > 0
|
71
|
+
tmp << lst.to_s(16)
|
72
|
+
end
|
73
|
+
ipv6.push(tmp)
|
74
|
+
end
|
75
|
+
ipv6.join(':').gsub(/:{2,}/, "::")
|
76
|
+
end
|
77
|
+
|
52
78
|
### Write methods ###
|
53
79
|
def write_int8(v, out)
|
54
80
|
v = v.to_i
|
55
81
|
raise_error "Too large int8 number: #{v}" if v > 0xFF # Max 255
|
82
|
+
raise_error "a negative number passed to int8 number: #{v}" if v < 0
|
56
83
|
out << v
|
57
84
|
end
|
58
85
|
|
59
86
|
def write_int16(v, out)
|
60
87
|
v = v.to_i
|
61
88
|
raise_error "Too large int16 number: #{v}" if v > 0xFFFF # Max 65.535
|
89
|
+
raise_error "a negative number passed to int16 number: #{v}" if v < 0
|
62
90
|
write_int8( v >> 8 & 0xFF, out)
|
63
91
|
write_int8( v & 0xFF, out)
|
64
92
|
end
|
@@ -66,6 +94,7 @@ module Divine
|
|
66
94
|
def write_int24(v, out)
|
67
95
|
v = v.to_i
|
68
96
|
raise_error "Too large int24 number: #{v}" if v > 0xFFFFFF # Max 16.777.215
|
97
|
+
raise_error "a negative number passed to int24 number: #{v}" if v < 0 # In Case added to ruby declaration
|
69
98
|
write_int8( v >> 16 & 0xFF, out)
|
70
99
|
write_int16( v & 0xFFFF, out)
|
71
100
|
end
|
@@ -73,6 +102,7 @@ module Divine
|
|
73
102
|
def write_int32(v, out)
|
74
103
|
v = v.to_i
|
75
104
|
raise_error "Too large int32 number: #{v}" if v > 0xFFFFFFFF # Max 4.294.967.295
|
105
|
+
raise_error "a negative number passed to int32 number: #{v}" if v < 0
|
76
106
|
write_int8( v >> 24 & 0xFF, out)
|
77
107
|
write_int24( v & 0xFFFFFF, out)
|
78
108
|
end
|
@@ -105,6 +135,19 @@ module Divine
|
|
105
135
|
end
|
106
136
|
end
|
107
137
|
|
138
|
+
def write_16_binary(v, out)
|
139
|
+
if v.is_a?(Array)
|
140
|
+
raise_error "Too large 16 binary: #{v.size} (#{v.class.name})" unless v.size*2 < 0xFF
|
141
|
+
write_int8(v.size * 2, out) # IPv6 consists of 8 parts each of them has zise of 2 bytes
|
142
|
+
v.each do |x|
|
143
|
+
write_int16(x, out)
|
144
|
+
end
|
145
|
+
else
|
146
|
+
raise_error "Unsupported binary 'nil'" if v == nil
|
147
|
+
raise_error "Unsupported binary of type '#{v.class.name}'"
|
148
|
+
end
|
149
|
+
end
|
150
|
+
|
108
151
|
def write_short_binary(v, out)
|
109
152
|
if v.is_a?(Array)
|
110
153
|
raise_error "Too large short_binary: #{v.size} (#{v.class.name})" unless v.size < 0xFF
|
@@ -123,6 +166,24 @@ module Divine
|
|
123
166
|
end
|
124
167
|
|
125
168
|
def write_ip_number(v, out)
|
169
|
+
if v.is_a?(Array)
|
170
|
+
if v.size == 4
|
171
|
+
write_ipv4_number(v, out);
|
172
|
+
else
|
173
|
+
write_ipv6_number(v, out);
|
174
|
+
end
|
175
|
+
elsif v.is_a?(String)
|
176
|
+
if v.include?":"
|
177
|
+
write_ipv6_number(v, out);
|
178
|
+
else
|
179
|
+
write_ipv4_number(v, out);
|
180
|
+
end
|
181
|
+
else
|
182
|
+
raise_error "Unknown IP number '#{v}'"
|
183
|
+
end
|
184
|
+
end
|
185
|
+
|
186
|
+
def write_ipv4_number(v,out)
|
126
187
|
if v.is_a?(Array)
|
127
188
|
raise_error "Unknown IP v4 number #{v}" unless v.size == 0 || v.size == 4 # Only IPv4 for now
|
128
189
|
write_short_binary(v, out)
|
@@ -130,12 +191,36 @@ module Divine
|
|
130
191
|
ss = v.split(/\./).map do |s|
|
131
192
|
s.to_i
|
132
193
|
end
|
133
|
-
|
194
|
+
write_ipv4_number(ss, out)
|
134
195
|
else
|
135
196
|
raise_error "Unknown IP number '#{v}'"
|
136
197
|
end
|
137
198
|
end
|
138
199
|
|
200
|
+
def write_ipv6_number(v, out)
|
201
|
+
if v.is_a?(Array)
|
202
|
+
write_16_binary(v, out)
|
203
|
+
elsif v.is_a?(String)
|
204
|
+
v = v.gsub(" ","") + " " # Temporary: To avoid the split problem when we have : at the end of "v"
|
205
|
+
raise_error "Unknown IPv6 number #{v}" unless v.strip.empty? ||
|
206
|
+
v.strip.match(/[^:0-9a-f]+/i) == nil && #Should not contains numbers or letters 0-9a-f
|
207
|
+
v.strip.match(/[0-9a-f]+/i) != nil && #Should contains numbers or letters 0-9a-f
|
208
|
+
v.match(":{3,}") == nil &&
|
209
|
+
v.split("::").size <= 2
|
210
|
+
ss = v.split(/:/).map do |s|
|
211
|
+
s = s.strip
|
212
|
+
raise_error "Unknown IPv6 Group #{s}" unless s.size <= 4
|
213
|
+
s.to_i 16
|
214
|
+
end
|
215
|
+
ss = [] if v.strip.empty?
|
216
|
+
raise_error "Unknown IPv6 number #{v}" unless (!v.include?("::") && ss.size == 0 || ss.size == 8) ||
|
217
|
+
(v.include?("::") && ss.size > 2 && ss.size < 8)
|
218
|
+
write_ipv6_number(ss, out)
|
219
|
+
else
|
220
|
+
raise_error "Unknown IPv6 number '#{v}'"
|
221
|
+
end
|
222
|
+
end
|
223
|
+
|
139
224
|
private
|
140
225
|
def raise_error(msg)
|
141
226
|
raise "[#{self.class.name}] #{msg}"
|
@@ -335,7 +420,7 @@ module Divine
|
|
335
420
|
# User defined super class?
|
336
421
|
toplevel = opts[:parent_class] || nil
|
337
422
|
toplevel = " < #{toplevel}" if toplevel
|
338
|
-
return "#{ruby_get_begin_module(opts)}#{base_template.result({ toplevel_class: toplevel })}\n\n#{src.join("\n\n")}#{ruby_get_end_module(opts)}"
|
423
|
+
return [{file: opts[:file], src: "#{ruby_get_begin_module(opts)}#{base_template.result({ toplevel_class: toplevel })}\n\n#{src.join("\n\n")}#{ruby_get_end_module(opts)}"}]
|
339
424
|
end
|
340
425
|
|
341
426
|
def ruby_get_begin_module(opts)
|
@@ -357,4 +442,4 @@ module Divine
|
|
357
442
|
|
358
443
|
|
359
444
|
$language_generators[:ruby] = RubyGenerator.new
|
360
|
-
end
|
445
|
+
end
|
data/lib/divine/version.rb
CHANGED
@@ -0,0 +1,34 @@
|
|
1
|
+
|
2
|
+
require 'divine'
|
3
|
+
|
4
|
+
struct 'TestBasic' do
|
5
|
+
int8 :i8
|
6
|
+
int16 :i16
|
7
|
+
int32 :i32
|
8
|
+
string :str
|
9
|
+
ip_number :ip
|
10
|
+
binary :guid
|
11
|
+
end
|
12
|
+
|
13
|
+
struct 'Entry' do
|
14
|
+
|
15
|
+
end
|
16
|
+
|
17
|
+
|
18
|
+
struct(:TestComplex) {
|
19
|
+
list :list1, :int32
|
20
|
+
list :list2, :int8
|
21
|
+
map :map1, :int8, :int32
|
22
|
+
map(:map2, :string) {
|
23
|
+
list 'Entry'
|
24
|
+
}
|
25
|
+
}
|
26
|
+
|
27
|
+
if ARGV[0] == "ruby"
|
28
|
+
Divine::CodeGenerator.new.generate(:ruby, file: 'test_babel.rb', module: 'BabelTest', parent_class: "Object", target_dir: 'test/basic_complex_test/ruby_test')
|
29
|
+
elsif ARGV[0] == "js"
|
30
|
+
Divine::CodeGenerator.new.generate(:javascript, file: 'test_babel.js', target_dir: 'test/basic_complex_test/js_test')
|
31
|
+
elsif ARGV[0] == "java"
|
32
|
+
Divine::CodeGenerator.new.generate(:java, file: 'test_babel.java', target_dir: 'test/basic_complex_test/java_test')
|
33
|
+
end
|
34
|
+
|
@@ -0,0 +1,96 @@
|
|
1
|
+
|
2
|
+
import java.io.ByteArrayInputStream;
|
3
|
+
import java.io.File;
|
4
|
+
import java.io.FileInputStream;
|
5
|
+
import java.io.FileOutputStream;
|
6
|
+
import java.io.IOException;
|
7
|
+
import java.util.ArrayList;
|
8
|
+
import java.util.Collections;
|
9
|
+
import java.util.HashMap;
|
10
|
+
import org.junit.*;
|
11
|
+
|
12
|
+
public class JavaTest {
|
13
|
+
|
14
|
+
@Test
|
15
|
+
public void testBasicTest() throws IOException {
|
16
|
+
System.out.println("Test Basic Test");
|
17
|
+
TestBasic testbasic_ser = new TestBasic();
|
18
|
+
TestBasic testbasic_deser = new TestBasic();
|
19
|
+
|
20
|
+
testbasic_ser.i8 = 16;
|
21
|
+
testbasic_ser.i16 = 458;
|
22
|
+
testbasic_ser.i32 = 365248;
|
23
|
+
testbasic_ser.str = "Testing String";
|
24
|
+
testbasic_ser.ip = "";
|
25
|
+
|
26
|
+
serialize(testbasic_ser);
|
27
|
+
byte[] read = deserialize();
|
28
|
+
testbasic_deser.deserialize(new ByteArrayInputStream(read));
|
29
|
+
|
30
|
+
org.junit.Assert.assertEquals(testbasic_ser.i8, testbasic_deser.i8);
|
31
|
+
org.junit.Assert.assertEquals(testbasic_ser.i16, testbasic_deser.i16);
|
32
|
+
org.junit.Assert.assertEquals(testbasic_ser.i32, testbasic_deser.i32);
|
33
|
+
org.junit.Assert.assertEquals(testbasic_ser.str, testbasic_deser.str);
|
34
|
+
org.junit.Assert.assertEquals(testbasic_ser.ip, testbasic_deser.ip);
|
35
|
+
}
|
36
|
+
|
37
|
+
@Test
|
38
|
+
public void testComplexTest() throws IOException {
|
39
|
+
TestComplex testcomplex_ser = new TestComplex();
|
40
|
+
TestComplex testcomplex_deser = new TestComplex();
|
41
|
+
testcomplex_ser.list1 = new ArrayList<Long>();
|
42
|
+
testcomplex_ser.list1.add(123456L);
|
43
|
+
testcomplex_ser.list1.add(654321L);
|
44
|
+
|
45
|
+
testcomplex_ser.list2 = new ArrayList<Integer>();
|
46
|
+
testcomplex_ser.list2.add(123);
|
47
|
+
testcomplex_ser.list2.add(221);
|
48
|
+
|
49
|
+
testcomplex_ser.map1 = new HashMap<Integer, Long>();
|
50
|
+
testcomplex_ser.map1.put(12, 123456L);
|
51
|
+
testcomplex_ser.map1.put(13, 6543231L);
|
52
|
+
|
53
|
+
testcomplex_ser.map2 = new HashMap<String, ArrayList<Entry>>();
|
54
|
+
ArrayList<Entry> tmp = new ArrayList<Entry>();
|
55
|
+
tmp.add(new Entry());
|
56
|
+
tmp.add(new Entry());
|
57
|
+
testcomplex_ser.map2.put("Key_1", tmp);
|
58
|
+
testcomplex_ser.map2.put("Key_2", tmp);
|
59
|
+
|
60
|
+
serialize(testcomplex_ser);
|
61
|
+
byte[] read = deserialize();
|
62
|
+
testcomplex_deser.deserialize(new ByteArrayInputStream(read));
|
63
|
+
|
64
|
+
org.junit.Assert.assertTrue (testcomplex_ser.list1.containsAll(testcomplex_deser.list1));
|
65
|
+
org.junit.Assert.assertTrue (testcomplex_ser.list2.containsAll(testcomplex_deser.list2));
|
66
|
+
for (Integer k : testcomplex_ser.map1.keySet()){
|
67
|
+
org.junit.Assert.assertEquals(testcomplex_ser.map1.get(k), testcomplex_deser.map1.get(k));
|
68
|
+
}
|
69
|
+
for (String k : testcomplex_ser.map2.keySet()){
|
70
|
+
org.junit.Assert.assertEquals(testcomplex_ser.map2.get(k).size(), testcomplex_deser.map2.get(k).size() );
|
71
|
+
}
|
72
|
+
|
73
|
+
}
|
74
|
+
|
75
|
+
public void serialize(BabelBase obj) throws IOException {
|
76
|
+
byte[] data = obj.serialize();
|
77
|
+
File file = new File("test/basic_complex_test/java_test/bin.babel");
|
78
|
+
try {
|
79
|
+
new FileOutputStream(file).write(data);
|
80
|
+
} catch (Exception e) {
|
81
|
+
e.printStackTrace();
|
82
|
+
}
|
83
|
+
}
|
84
|
+
|
85
|
+
public byte[] deserialize() throws IOException{
|
86
|
+
File file = new File("test/basic_complex_test/java_test/bin.babel");
|
87
|
+
byte[] data = new byte[(int) file.length()];
|
88
|
+
try {
|
89
|
+
new FileInputStream(file).read(data);
|
90
|
+
} catch (Exception e) {
|
91
|
+
e.printStackTrace();
|
92
|
+
}
|
93
|
+
return data;
|
94
|
+
}
|
95
|
+
|
96
|
+
}
|
@@ -0,0 +1,368 @@
|
|
1
|
+
import java.io.ByteArrayInputStream;
|
2
|
+
import java.io.ByteArrayOutputStream;
|
3
|
+
import java.io.IOException;
|
4
|
+
import java.util.ArrayList;
|
5
|
+
import java.util.HashMap;
|
6
|
+
import java.util.regex.Pattern;
|
7
|
+
import java.nio.charset.Charset;
|
8
|
+
|
9
|
+
abstract class BabelBase {
|
10
|
+
private static final Charset UTF8 = Charset.forName("UTF-8");
|
11
|
+
|
12
|
+
public byte[] serialize() throws IOException {
|
13
|
+
ByteArrayOutputStream baos = new ByteArrayOutputStream();
|
14
|
+
serializeInternal(baos);
|
15
|
+
baos.close();
|
16
|
+
return baos.toByteArray();
|
17
|
+
}
|
18
|
+
|
19
|
+
abstract void serializeInternal(ByteArrayOutputStream baos) throws IOException;
|
20
|
+
|
21
|
+
abstract void deserialize(ByteArrayInputStream baos) throws IOException;
|
22
|
+
|
23
|
+
protected int readInt8(ByteArrayInputStream data) {
|
24
|
+
return data.read() & 0xff;
|
25
|
+
}
|
26
|
+
|
27
|
+
protected int readInt16(ByteArrayInputStream data) {
|
28
|
+
return (data.read() << 8) | readInt8(data);
|
29
|
+
}
|
30
|
+
|
31
|
+
protected int readInt24(ByteArrayInputStream data) {
|
32
|
+
return (data.read() << 16) | readInt16(data);
|
33
|
+
}
|
34
|
+
|
35
|
+
protected long readInt32(ByteArrayInputStream data) {
|
36
|
+
return (data.read() << 24) | readInt24(data);
|
37
|
+
}
|
38
|
+
|
39
|
+
protected boolean readBool(ByteArrayInputStream data) {
|
40
|
+
return readInt8(data) == 1;
|
41
|
+
}
|
42
|
+
|
43
|
+
protected String readString(ByteArrayInputStream data) throws IOException {
|
44
|
+
// Force utf8
|
45
|
+
return new String(readBytes(readInt16(data), data), UTF8);
|
46
|
+
}
|
47
|
+
|
48
|
+
private byte[] readBytes(int size, ByteArrayInputStream data) throws IOException {
|
49
|
+
byte[] bs = new byte[size];
|
50
|
+
data.read(bs);
|
51
|
+
return bs;
|
52
|
+
}
|
53
|
+
|
54
|
+
protected byte[] readBinary(ByteArrayInputStream data) throws IOException {
|
55
|
+
long c = readInt32(data);
|
56
|
+
if (c > Integer.MAX_VALUE) {
|
57
|
+
throw new IndexOutOfBoundsException("Binary data to big for java");
|
58
|
+
}
|
59
|
+
return readBytes((int) c, data);
|
60
|
+
}
|
61
|
+
|
62
|
+
protected byte[] readShortBinary(ByteArrayInputStream data) throws IOException {
|
63
|
+
return readBytes(readInt8(data), data);
|
64
|
+
}
|
65
|
+
|
66
|
+
protected String readIpNumber(ByteArrayInputStream data) throws IOException {
|
67
|
+
byte[] ips = readShortBinary(data);
|
68
|
+
if(ips.length == 4){
|
69
|
+
return readIpv4Number(ips);
|
70
|
+
} else{
|
71
|
+
return readIpv6Number(ips);
|
72
|
+
}
|
73
|
+
}
|
74
|
+
|
75
|
+
protected String readIpv4Number(byte[] ips){
|
76
|
+
String ip = "";
|
77
|
+
for (byte b : ips) {
|
78
|
+
if (ip.length() > 0) {
|
79
|
+
ip += ".";
|
80
|
+
}
|
81
|
+
ip += (b & 0xFF);
|
82
|
+
}
|
83
|
+
return ip;
|
84
|
+
}
|
85
|
+
|
86
|
+
protected String readIpv6Number(byte[] ips) throws IOException {
|
87
|
+
String ip = "";
|
88
|
+
int part1, part2;
|
89
|
+
for (int i = 0; i < ips.length; i+=2) {
|
90
|
+
part1 = ips[i] & 0xFF;
|
91
|
+
part2 = ips[i+1] & 0xFF;
|
92
|
+
ip += part1 == 0? "" : Integer.toHexString(part1);
|
93
|
+
ip += (part1 == 0 && part2 == 0)? "" : (part2 < 10 && part1 != 0? "0" + Integer.toHexString(part2): Integer.toHexString(part2));
|
94
|
+
if (i < ips.length-2) {
|
95
|
+
ip += ":";
|
96
|
+
}
|
97
|
+
}
|
98
|
+
ip = ip.replaceAll(":{3,}", "::");
|
99
|
+
return ip;
|
100
|
+
}
|
101
|
+
|
102
|
+
protected void writeInt8(int v, ByteArrayOutputStream out) {
|
103
|
+
if (v > 0xFF) { // Max 255
|
104
|
+
raiseError("Too large int8 number: " + v);
|
105
|
+
}else if(v < 0){
|
106
|
+
raiseError("a negative number passed to int8 number: " + v);
|
107
|
+
}
|
108
|
+
out.write(v);
|
109
|
+
}
|
110
|
+
|
111
|
+
protected void writeInt16(int v, ByteArrayOutputStream out) {
|
112
|
+
if (v > 0xFFFF) { // Max 65.535
|
113
|
+
raiseError("Too large int16 number: " + v);
|
114
|
+
}else if(v < 0){
|
115
|
+
raiseError("a negative number passed to int16 number: " + v);
|
116
|
+
}
|
117
|
+
writeInt8(v >> 8 & 0xFF, out);
|
118
|
+
writeInt8(v & 0xFF, out);
|
119
|
+
}
|
120
|
+
|
121
|
+
protected void writeInt24(int v, ByteArrayOutputStream out) {
|
122
|
+
if (v > 0xFFFFFF) { // Max 16.777.215
|
123
|
+
raiseError("Too large int24 number: " + v);
|
124
|
+
}else if(v < 0){ // In Case added to Java declaration
|
125
|
+
raiseError("a negative number passed to int24 number: " + v);
|
126
|
+
}
|
127
|
+
writeInt8(v >> 16 & 0xFF, out);
|
128
|
+
writeInt16(v & 0xFFFF, out);
|
129
|
+
}
|
130
|
+
|
131
|
+
protected void writeInt32(long v, ByteArrayOutputStream out) {
|
132
|
+
if (v > 0xFFFFFFFFL) { // Max 4.294.967.295
|
133
|
+
raiseError("Too large int32 number: " + v);
|
134
|
+
}else if(v < 0){
|
135
|
+
raiseError("a negative number passed to int32 number: " + v);
|
136
|
+
}
|
137
|
+
writeInt8((int) ((v >> 24) & 0xFF), out);
|
138
|
+
writeInt24((int) (v & 0xFFFFFF), out);
|
139
|
+
}
|
140
|
+
|
141
|
+
protected void writeBool(boolean v, ByteArrayOutputStream out) {
|
142
|
+
writeInt8(v ? 1 : 0, out);
|
143
|
+
}
|
144
|
+
|
145
|
+
protected void writeString(String v, ByteArrayOutputStream out) throws IOException {
|
146
|
+
byte[] bs = v.getBytes(UTF8);
|
147
|
+
if (bs.length > 0xFFFF) {
|
148
|
+
raiseError("Too large string: " + bs.length + " bytes");
|
149
|
+
}
|
150
|
+
writeInt16(bs.length, out);
|
151
|
+
out.write(bs);
|
152
|
+
}
|
153
|
+
|
154
|
+
protected void writeBinary(byte[] v, ByteArrayOutputStream out) throws IOException {
|
155
|
+
if (v.length > 0xFFFFFFFFL) {
|
156
|
+
raiseError("Too large binary: " + v.length + " bytes");
|
157
|
+
}
|
158
|
+
writeInt32(v.length, out);
|
159
|
+
out.write(v);
|
160
|
+
}
|
161
|
+
|
162
|
+
|
163
|
+
protected void write16Binary(int[] v, ByteArrayOutputStream out) throws IOException {
|
164
|
+
if (v.length > 0xFF) {
|
165
|
+
raiseError("Too large 16_binary: " + (v.length*2) + " bytes");
|
166
|
+
}
|
167
|
+
writeInt8(v.length*2, out);
|
168
|
+
for(int i = 0; i < v.length; i++){
|
169
|
+
this.writeInt16(v[i], out);
|
170
|
+
}
|
171
|
+
}
|
172
|
+
|
173
|
+
protected void writeShortBinary(byte[] v, ByteArrayOutputStream out) throws IOException {
|
174
|
+
if (v.length > 0xFF) {
|
175
|
+
raiseError("Too large short_binary: " + v.length + " bytes");
|
176
|
+
}
|
177
|
+
writeInt8(v.length, out);
|
178
|
+
out.write(v);
|
179
|
+
}
|
180
|
+
|
181
|
+
protected void writeIpNumber(String v, ByteArrayOutputStream out) throws IOException {
|
182
|
+
if(v.contains(":")){
|
183
|
+
writeIpv6Number( v, out);
|
184
|
+
}else{
|
185
|
+
writeIpv4Number( v, out);
|
186
|
+
}
|
187
|
+
}
|
188
|
+
|
189
|
+
protected void writeIpv4Number(String v, ByteArrayOutputStream out) throws IOException {
|
190
|
+
byte[] ss = new byte[0];
|
191
|
+
if(!v.isEmpty()){
|
192
|
+
String[] bs = v.split("\\.");
|
193
|
+
ss = new byte[bs.length];
|
194
|
+
for (int i = 0; i < bs.length; i++) {
|
195
|
+
ss[i] = (byte) (Integer.parseInt(bs[i]) & 0xFF);
|
196
|
+
}
|
197
|
+
}
|
198
|
+
if (ss.length == 0 || ss.length == 4) {
|
199
|
+
writeShortBinary(ss, out);
|
200
|
+
} else {
|
201
|
+
raiseError("Unknown IP v4 number " + v); // Only IPv4 for now
|
202
|
+
}
|
203
|
+
}
|
204
|
+
|
205
|
+
protected void writeIpv6Number(String v, ByteArrayOutputStream out)
|
206
|
+
throws IOException {
|
207
|
+
v = v.replaceAll(" ", "") + " "; // Temporary: To avoid the split problem when we have : at the
|
208
|
+
// end of "v"
|
209
|
+
int[] ss = new int[0];
|
210
|
+
boolean contains_ipv6_letters = Pattern.compile("[0-9a-f]+").matcher(
|
211
|
+
v.trim().toLowerCase()).find();
|
212
|
+
boolean contains_other_letters = Pattern.compile("[^:0-9a-f]+")
|
213
|
+
.matcher(v.trim().toLowerCase()).find();
|
214
|
+
// make sure of v must have only one "::" and no more than two of ":".
|
215
|
+
// e.g. 1::1::1 & 1:::1:205
|
216
|
+
if (!v.trim().isEmpty() && v.split(":{3,}").length == 1
|
217
|
+
&& v.split(":{2}").length <= 2 && !contains_other_letters
|
218
|
+
&& contains_ipv6_letters) {
|
219
|
+
String[] bs = v.split(":");
|
220
|
+
ss = new int[bs.length];
|
221
|
+
for (int i = 0; i < bs.length; i++) {
|
222
|
+
String s = bs[i].trim();
|
223
|
+
if (s.length() <= 4) // to avoid such number 0125f
|
224
|
+
ss[i] = Integer.parseInt(
|
225
|
+
(s.isEmpty() ? "0" : bs[i].trim()), 16);
|
226
|
+
else
|
227
|
+
raiseError("Unknown IPv6 Group " + i + " which is " + s);
|
228
|
+
}
|
229
|
+
}
|
230
|
+
// Check for make sure of the size of the IP groups in case "::" is used
|
231
|
+
// [> 2 & < 8]or not [must == 8]
|
232
|
+
if (!contains_other_letters
|
233
|
+
&& (!v.contains("::") && ss.length == 0 || ss.length == 8)
|
234
|
+
|| (v.contains("::") && ss.length > 2 && ss.length < 8)) {
|
235
|
+
write16Binary(ss, out);
|
236
|
+
} else {
|
237
|
+
raiseError("Unknown IP v6 number " + v);
|
238
|
+
}
|
239
|
+
}
|
240
|
+
|
241
|
+
protected void raiseError(String msg) {
|
242
|
+
throw new IllegalArgumentException("[" + this.getClass().getCanonicalName() + "] " + msg);
|
243
|
+
}
|
244
|
+
}
|
245
|
+
|
246
|
+
|
247
|
+
class Entry extends BabelBase {
|
248
|
+
|
249
|
+
@Override
|
250
|
+
void serializeInternal(ByteArrayOutputStream baos) throws IOException {
|
251
|
+
}
|
252
|
+
|
253
|
+
@Override
|
254
|
+
public void deserialize(ByteArrayInputStream bais) throws IOException {
|
255
|
+
}
|
256
|
+
}
|
257
|
+
|
258
|
+
|
259
|
+
class TestBasic extends BabelBase {
|
260
|
+
public int i8 = 0;
|
261
|
+
public int i16 = 0;
|
262
|
+
public long i32 = 0L;
|
263
|
+
public String str = "";
|
264
|
+
public String ip = "";
|
265
|
+
public byte[] guid = new byte[0];
|
266
|
+
|
267
|
+
@Override
|
268
|
+
void serializeInternal(ByteArrayOutputStream baos) throws IOException {
|
269
|
+
writeInt8(this.i8, baos);
|
270
|
+
writeInt16(this.i16, baos);
|
271
|
+
writeInt32(this.i32, baos);
|
272
|
+
writeString(this.str, baos);
|
273
|
+
writeIpNumber(this.ip, baos);
|
274
|
+
writeBinary(this.guid, baos);
|
275
|
+
}
|
276
|
+
|
277
|
+
@Override
|
278
|
+
public void deserialize(ByteArrayInputStream bais) throws IOException {
|
279
|
+
this.i8 = readInt8(bais);
|
280
|
+
this.i16 = readInt16(bais);
|
281
|
+
this.i32 = readInt32(bais);
|
282
|
+
this.str = readString(bais);
|
283
|
+
this.ip = readIpNumber(bais);
|
284
|
+
this.guid = readBinary(bais);
|
285
|
+
}
|
286
|
+
}
|
287
|
+
|
288
|
+
|
289
|
+
class TestComplex extends BabelBase {
|
290
|
+
public ArrayList<Long> list1 = new ArrayList<Long>();
|
291
|
+
public ArrayList<Integer> list2 = new ArrayList<Integer>();
|
292
|
+
public HashMap<Integer, Long> map1 = new HashMap<Integer, Long>();
|
293
|
+
public HashMap<String, ArrayList<Entry>> map2 = new HashMap<String, ArrayList<Entry>>();
|
294
|
+
|
295
|
+
@Override
|
296
|
+
void serializeInternal(ByteArrayOutputStream baos) throws IOException {
|
297
|
+
// Serialize list 'list1'
|
298
|
+
writeInt32(list1.size(), baos);
|
299
|
+
for(int var_101=0; var_101<list1.size(); var_101++) {
|
300
|
+
long var_100 = list1.get(var_101);
|
301
|
+
writeInt32(var_100, baos);
|
302
|
+
}
|
303
|
+
// Serialize list 'list2'
|
304
|
+
writeInt32(list2.size(), baos);
|
305
|
+
for(int var_103=0; var_103<list2.size(); var_103++) {
|
306
|
+
int var_102 = list2.get(var_103);
|
307
|
+
writeInt8(var_102, baos);
|
308
|
+
}
|
309
|
+
// Serialize map 'map1'
|
310
|
+
writeInt32(map1.size(), baos);
|
311
|
+
for(int var_104 : map1.keySet()) {
|
312
|
+
long var_105 = map1.get(var_104);
|
313
|
+
writeInt8(var_104, baos);
|
314
|
+
writeInt32(var_105, baos);
|
315
|
+
}
|
316
|
+
// Serialize map 'map2'
|
317
|
+
writeInt32(map2.size(), baos);
|
318
|
+
for(String var_106 : map2.keySet()) {
|
319
|
+
ArrayList<Entry> var_107 = map2.get(var_106);
|
320
|
+
writeString(var_106, baos);
|
321
|
+
writeInt32(var_107.size(), baos);
|
322
|
+
for(int var_109=0; var_109<var_107.size(); var_109++) {
|
323
|
+
Entry var_108 = var_107.get(var_109);
|
324
|
+
var_108.serializeInternal(baos);
|
325
|
+
}
|
326
|
+
}
|
327
|
+
}
|
328
|
+
|
329
|
+
@Override
|
330
|
+
public void deserialize(ByteArrayInputStream bais) throws IOException {
|
331
|
+
// Deserialize list 'list1'
|
332
|
+
this.list1 = new ArrayList<Long>();
|
333
|
+
int var_10a = (int)this.readInt32(bais);
|
334
|
+
for(int var_10c=0; var_10c<var_10a; var_10c++) {
|
335
|
+
long var_10b = readInt32(bais);
|
336
|
+
this.list1.add(var_10b);
|
337
|
+
}
|
338
|
+
// Deserialize list 'list2'
|
339
|
+
this.list2 = new ArrayList<Integer>();
|
340
|
+
int var_10d = (int)this.readInt32(bais);
|
341
|
+
for(int var_10f=0; var_10f<var_10d; var_10f++) {
|
342
|
+
int var_10e = readInt8(bais);
|
343
|
+
this.list2.add(var_10e);
|
344
|
+
}
|
345
|
+
// Deserialize map 'map1'
|
346
|
+
this.map1 = new HashMap<Integer, Long>();
|
347
|
+
int var_110 = (int)readInt32(bais);
|
348
|
+
for(int var_113=0; var_113<var_110; var_113++) {
|
349
|
+
int var_111 = readInt8(bais);
|
350
|
+
long var_112 = readInt32(bais);
|
351
|
+
this.map1.put(var_111, var_112);
|
352
|
+
}
|
353
|
+
// Deserialize map 'map2'
|
354
|
+
this.map2 = new HashMap<String, ArrayList<Entry>>();
|
355
|
+
int var_114 = (int)readInt32(bais);
|
356
|
+
for(int var_117=0; var_117<var_114; var_117++) {
|
357
|
+
String var_115 = readString(bais);
|
358
|
+
ArrayList<Entry> var_116 = new ArrayList<Entry>();
|
359
|
+
int var_118 = (int)this.readInt32(bais);
|
360
|
+
for(int var_11a=0; var_11a<var_118; var_11a++) {
|
361
|
+
Entry var_119 = new Entry();
|
362
|
+
var_119.deserialize(bais);
|
363
|
+
var_116.add(var_119);
|
364
|
+
}
|
365
|
+
this.map2.put(var_115, var_116);
|
366
|
+
}
|
367
|
+
}
|
368
|
+
}
|