leon 1.0.0

Sign up to get free protection for your applications and to get access to all the features.
@@ -0,0 +1,68 @@
1
+ require 'constants'
2
+
3
+ module LEON
4
+ class BufferIterator
5
+ def initialize(buf)
6
+ @buffer = buf
7
+ @i = 0
8
+ end
9
+ def readUInt8()
10
+ @i += 1
11
+ return @buffer.readUInt8(@i - 1)
12
+ end
13
+ def readInt8()
14
+ @i += 1
15
+ return @buffer.readInt8(@i - 1)
16
+ end
17
+ def readUInt16()
18
+ @i += 2
19
+ return @buffer.readUInt16LE(@i - 2)
20
+ end
21
+ def readInt16()
22
+ @i += 2
23
+ return @buffer.readInt16LE(@i - 2)
24
+ end
25
+ def readUInt32()
26
+ @i += 4
27
+ return @buffer.readUInt32LE(@i - 4)
28
+ end
29
+ def readInt32()
30
+ @i += 4
31
+ return @buffer.readInt32LE(@i - 4)
32
+ end
33
+ def readFloat()
34
+ @i += 4
35
+ return @buffer.readFloatLE(@i - 4)
36
+ end
37
+ def readDouble()
38
+ @i += 8
39
+ return @buffer.readDoubleLE(@i - 8)
40
+ end
41
+ def readValue(type)
42
+ if type === Constants::UNSIGNED_CHAR
43
+ return readUInt8()
44
+ end
45
+ if type === Constants::CHAR
46
+ return readInt8()
47
+ end
48
+ if type === Constants::UNSIGNED_SHORT
49
+ return readUInt16()
50
+ end
51
+ if type === Constants::SHORT
52
+ return readInt16()
53
+ end
54
+ if type === Constants::UNSIGNED_INT
55
+ return readUInt32()
56
+ end
57
+ if type === Constants::INT
58
+ return readInt32()
59
+ end
60
+ if type === Constants::FLOAT
61
+ return readFloat()
62
+ end
63
+ if type === Constants::DOUBLE
64
+ return readDouble()
65
+ end
66
+ end
67
+ end
68
+ end
data/lib/constants.rb ADDED
@@ -0,0 +1,22 @@
1
+ module Constants
2
+ UNSIGNED_CHAR = 0x00
3
+ CHAR = 0x01
4
+ UNSIGNED_SHORT = 0x02
5
+ SHORT = 0x03
6
+ UNSIGNED_INT = 0x04
7
+ INT = 0x05
8
+ FLOAT = 0x06
9
+ DOUBLE = 0x07
10
+ STRING = 0x10
11
+ BOOLEAN = 0x20
12
+ NULL = 0x40
13
+ UNDEFINED = 0x14
14
+ OBJECT = 0x09
15
+ ARRAY = 0x80
16
+ DATE = 0x15
17
+ BUFFER = 0x16
18
+ REGEXP = 0x17
19
+ NAN = 0x18
20
+ INFINITY = 0x19
21
+ MINUS_INFINITY = 0x1A
22
+ end
data/lib/io.rb ADDED
@@ -0,0 +1,525 @@
1
+ require 'buffer-iterator'
2
+ require 'string-buffer'
3
+ require 'constants'
4
+ require 'types'
5
+ require 'date'
6
+ require 'time'
7
+
8
+ module LEON
9
+ class Parser
10
+ def initialize(*args)
11
+ if args.length > 1
12
+ @spec = args[1]
13
+ @hasSpec = true
14
+ end
15
+ @buffer = BufferIterator.new(args[0])
16
+ @state = 0
17
+ @stringIndex = Array.new
18
+ @objectLayoutIndex = Array.new
19
+ end
20
+ def readString()
21
+ ret = ''
22
+ while (true) do
23
+ char = @buffer.readUInt8()
24
+ if char === 0
25
+ break
26
+ end
27
+ ret += char.chr
28
+ end
29
+ return ret
30
+ end
31
+ def readBuffer()
32
+ ret = StringBuffer.new
33
+ len = @buffer.readValue(@buffer.readUInt8())
34
+ for i in 0..(len - 1)
35
+ ret.writeUInt8(@buffer.readUInt8(), i)
36
+ end
37
+ return ret
38
+ end
39
+ def readRegExp()
40
+ return RegExp.new(readString(), readString())
41
+ end
42
+ def readDate()
43
+ return Time.at(@buffer.readUInt32())
44
+ end
45
+ def parseSI()
46
+ if (@state & 0x01) != 0
47
+ return
48
+ end
49
+ @stringIndexType = @buffer.readUInt8()
50
+ case @stringIndexType
51
+ when Constants::UNSIGNED_CHAR, Constants::UNSIGNED_SHORT, Constants::UNSIGNED_INT
52
+ stringCount = @buffer.readValue(@stringIndexType)
53
+ when 0xFF
54
+ stringCount = 0
55
+ else
56
+ return self
57
+ end
58
+ for i in (0..(stringCount - 1))
59
+ @stringIndex.push readString()
60
+ end
61
+ @state |= 0x01
62
+ return self
63
+ end
64
+ def parseOLI()
65
+ if (@state & 0x01) === 0
66
+ parseSI()
67
+ end
68
+ if @stringIndex.length === 0
69
+ return self
70
+ end
71
+ @OLItype = @buffer.readUInt8()
72
+ case @OLItype
73
+ when Constants::UNSIGNED_CHAR, Constants::UNSIGNED_SHORT, Constants::UNSIGNED_INT
74
+ count = @buffer.readValue(@OLItype)
75
+ when 0xFF
76
+ return self
77
+ else
78
+ return self
79
+ end
80
+ for i in 0..(count - 1)
81
+ @objectLayoutIndex.push Array.new
82
+ numFields = @buffer.readValue(@buffer.readUInt8())
83
+ for j in 0..(numFields - 1)
84
+ @objectLayoutIndex[i].push(@buffer.readValue(@stringIndexType))
85
+ end
86
+ end
87
+ return self
88
+ end
89
+ def parseValueWithSpec(*args)
90
+ if args.length === 0
91
+ spec = @spec
92
+ else
93
+ spec = args[0]
94
+ end
95
+ if spec === Constants::STRING
96
+ return readString()
97
+ elsif spec.kind_of?(Array)
98
+ ret = Array.new
99
+ spec = spec[0]
100
+ length = @buffer.readValue(@buffer.readUInt8())
101
+ for i in (0..(length - 1))
102
+ ret.push parseValueWithSpec(spec)
103
+ end
104
+ return ret
105
+ elsif spec.is_a?(Hash)
106
+ ret = Hash.new
107
+ spec.each do |k, v|
108
+ ret[k] = parseValueWithSpec(v)
109
+ end
110
+ return ret
111
+ elsif spec === Constants::BOOLEAN
112
+ return parseValue()
113
+ else
114
+ return parseValue(spec)
115
+ end
116
+ end
117
+ def parseValue(*args)
118
+ if args.length === 0
119
+ type = @buffer.readUInt8()
120
+ else
121
+ type = args[0]
122
+ end
123
+ if type < Constants::OBJECT
124
+ return @buffer.readValue(type)
125
+ elsif type === Constants::ARRAY
126
+ len = @buffer.readValue(@buffer.readUInt8())
127
+ ret = Array.new
128
+ for i in 0..(len - 1)
129
+ ret.push parseValue()
130
+ end
131
+ return ret
132
+ elsif type === Constants::OBJECT
133
+ index = @objectLayoutIndex[@buffer.readValue(@OLItype)]
134
+ ret = Hash.new
135
+ index.each_with_index { |val, idx|
136
+ ret[@stringIndex[val]] = parseValue()
137
+ }
138
+ return ret
139
+ elsif type === Constants::STRING
140
+ return @stringIndex[@buffer.readValue(@stringIndexType)]
141
+ elsif type === Constants::UNDEFINED
142
+ return LEON::Undefined.new
143
+ elsif type === Constants::BOOLEAN
144
+ return true
145
+ elsif type === Constants::BOOLEAN + 1
146
+ return false
147
+ elsif type === Constants::NULL
148
+ return nil
149
+ elsif type === Constants::NAN
150
+ return LEON::NaN.new
151
+ elsif type === Constants::DATE
152
+ return readDate()
153
+ elsif type === Constants::REGEXP
154
+ return readRegExp()
155
+ elsif type === Constants::BUFFER
156
+ return readBuffer()
157
+ elsif type === Constants::INFINITY
158
+ return Float::INFINITY
159
+ elsif type === Constants::MINUS_INFINITY
160
+ return -1/0.0
161
+ else
162
+ return
163
+ end
164
+ end
165
+ end
166
+
167
+ def self.type_check(v)
168
+ if v === nil
169
+ return Constants::NULL
170
+ elsif v === true
171
+ return Constants::BOOLEAN
172
+ elsif v === false
173
+ return Constants::BOOLEAN + 1
174
+ elsif v.kind_of? LEON::NaN
175
+ return Constants::NAN
176
+ elsif v.kind_of? LEON::Undefined
177
+ return Constants::UNDEFINED
178
+ elsif v.kind_of? Date or v.kind_of? Time
179
+ return Constants::DATE
180
+ elsif v.kind_of? LEON::StringBuffer
181
+ return Constants::BUFFER
182
+ elsif v.kind_of? LEON::RegExp
183
+ return Constants::REGEXP
184
+ elsif v === Float::INFINITY
185
+ return Constants::INFINITY
186
+ elsif v === -1/0.0
187
+ return Constants::MINUS_INFINITY
188
+ elsif v.kind_of?(Array)
189
+ return Constants::ARRAY
190
+ elsif v.kind_of?(Hash)
191
+ return Constants::OBJECT
192
+ elsif v.is_a? String
193
+ return Constants::STRING
194
+ elsif v.kind_of? Symbol
195
+ return Constants::STRING
196
+ elsif v.is_a? Fixnum
197
+ if v < 0
198
+ v = v.abs
199
+ if v < (1 << 6)
200
+ return Constants::CHAR
201
+ elsif v < (1 << 14)
202
+ return Constants::SHORT
203
+ elsif v < (1 << 30)
204
+ return Constants::INT
205
+ end
206
+ return Constants::DOUBLE
207
+ end
208
+ if v < (1 << 7)
209
+ return Constants::UNSIGNED_CHAR
210
+ end
211
+ if v < (1 << 15)
212
+ return Constants::UNSIGNED_SHORT
213
+ end
214
+ if v < (1 << 31)
215
+ return Constants::UNSIGNED_INT
216
+ end
217
+ return Constants::DOUBLE
218
+ elsif v.is_a? Float
219
+ v = v.abs
220
+ log = Math::log(v)/Math::log(2)
221
+ if log < -128 or log > 127
222
+ return Constants::DOUBLE
223
+ end
224
+ if log < 0
225
+ log = log.ceil
226
+ else
227
+ log = log.floor
228
+ end
229
+ v *= 2**(-log + 23)
230
+ if v.floor != v
231
+ return Constants::DOUBLE
232
+ end
233
+ return Constants::FLOAT
234
+ end
235
+ end
236
+
237
+ class Encoder
238
+ def initialize(*args)
239
+ if args.length > 1
240
+ @spec = args[1]
241
+ @hasSpec = true
242
+ else
243
+ @hasSpec = false
244
+ end
245
+ @payload = args[0]
246
+ @OLI = Array.new
247
+ @stringIndex = Array.new
248
+ @buffer = StringBuffer.new
249
+ end
250
+ def append(buf)
251
+ @buffer = StringBuffer.concat([@buffer, buf])
252
+ end
253
+ def writeData()
254
+ if @hasSpec
255
+ writeValueWithSpec(@payload)
256
+ else
257
+ writeValue(@payload, LEON::type_check(@payload))
258
+ end
259
+ return self
260
+ end
261
+ def export()
262
+ return @buffer.buffer
263
+ end
264
+ def writeValueWithSpec(*args)
265
+ if args.length > 1
266
+ spec = args[1]
267
+ else
268
+ spec = @spec
269
+ end
270
+ val = args[0]
271
+ if spec.kind_of? Array
272
+ writeValue(val.length, LEON::type_check(val.length))
273
+ val.each { |v|
274
+ writeValueWithSpec(v, spec[0])
275
+ }
276
+ elsif spec.kind_of? Hash
277
+ spec.each { |k, v|
278
+ writeValueWithSpec(val[k], v)
279
+ }
280
+ elsif spec === Constants::BOOLEAN
281
+ writeValue(val, LEON::type_check(val), true)
282
+ else
283
+ writeValue(val, spec, true)
284
+ end
285
+ end
286
+ def writeValue(*args)
287
+ val = args[0]
288
+ type = args[1]
289
+ if args.length > 2
290
+ implicit = args[2]
291
+ else
292
+ implicit = false
293
+ end
294
+ typeByte = StringBuffer.new
295
+ typeByte.writeUInt8(type, 0)
296
+ if type === Constants::UNDEFINED or type === Constants::BOOLEAN or type === Constants::BOOLEAN + 1 or type === Constants::NULL or type === Constants::NAN or type === Constants::MINUS_INFINITY or type === Constants::INFINITY
297
+ append(typeByte)
298
+ return 1
299
+ end
300
+ byteCount = 0
301
+ if !implicit
302
+ append(typeByte)
303
+ byteCount += 1
304
+ end
305
+ if type === Constants::STRING
306
+ if val.kind_of? Symbol
307
+ val = val.to_s
308
+ end
309
+ if @stringIndex.length === 0
310
+ writeString(val)
311
+ return 1 + byteCount + val.length
312
+ end
313
+ writeValue(@stringIndex.index(val), @stringIndexType, true)
314
+ return byteCount + 1
315
+ elsif type == Constants::CHAR
316
+ bytes = StringBuffer.new
317
+ bytes.writeInt8(val, 0)
318
+ append(bytes)
319
+ return byteCount + 1
320
+ elsif type == Constants::UNSIGNED_CHAR
321
+ bytes = StringBuffer.new
322
+ bytes.writeUInt8(val, 0)
323
+ append(bytes)
324
+ return byteCount + 1
325
+ elsif type === Constants::SHORT
326
+ bytes = StringBuffer.new
327
+ bytes.writeInt16LE(val, 0)
328
+ append(bytes)
329
+ return byteCount + 2
330
+ elsif type === Constants::UNSIGNED_SHORT
331
+ bytes = StringBuffer.new
332
+ bytes.writeUInt16LE(val, 0)
333
+ append(bytes)
334
+ return byteCount + 2
335
+ elsif type === Constants::INT
336
+ bytes = StringBuffer.new
337
+ bytes.writeInt32LE(val, 0)
338
+ append(bytes)
339
+ return byteCount + 4
340
+ elsif type === Constants::UNSIGNED_INT
341
+ bytes = StringBuffer.new
342
+ bytes.writeUInt32LE(val, 0)
343
+ append(bytes)
344
+ return byteCount + 4
345
+ elsif type === Constants::FLOAT
346
+ bytes = StringBuffer.new
347
+ bytes.writeFloatLE(val, 0)
348
+ append(bytes)
349
+ return byteCount + 4
350
+ elsif type === Constants::DOUBLE
351
+ bytes = StringBuffer.new
352
+ bytes.writeDoubleLE(val, 0)
353
+ append(bytes)
354
+ return byteCount + 8
355
+ elsif type === Constants::ARRAY
356
+ writeValue(val.length, LEON::type_check(val.length))
357
+ val.each { |v|
358
+ writeValue(v, LEON::type_check(v))
359
+ }
360
+ return
361
+ elsif type === Constants::OBJECT
362
+ index = LEON::match_layout(val, @stringIndex, @OLI)
363
+ writeValue(index, @OLItype, true)
364
+ for i in 0..(@OLI[index].length - 1)
365
+ key = @stringIndex[@OLI[index][i]]
366
+ if not val.has_key? key
367
+ key = key.to_sym
368
+ end
369
+ tmp = val[key]
370
+ writeValue(tmp, LEON::type_check(tmp))
371
+ end
372
+ return
373
+ elsif type === Constants::BUFFER
374
+ len = val.buffer.length
375
+ writeValue(len, LEON::type_check(len))
376
+ for i in 0..(len - 1)
377
+ writeValue(val.buffer[i].ord, Constants::UNSIGNED_CHAR, true)
378
+ end
379
+ return byteCount + val.buffer.length
380
+ elsif type === Constants::REGEXP
381
+ writeString(val.pattern)
382
+ writeString(val.modifier)
383
+ return byteCount + 2 + val.pattern.length + val.modifier.length
384
+ elsif type === Constants::DATE
385
+ if val.kind_of? Date
386
+ val = Time.parse(val.to_s)
387
+ end
388
+ writeValue(val.to_i, Constants::UNSIGNED_INT, true)
389
+ return byteCount + 4
390
+ end
391
+ end
392
+ def writeString(str)
393
+ bytes = StringBuffer.new
394
+ len = str.length
395
+ for i in 0..(len - 1)
396
+ bytes.writeUInt8(str[i].ord, -1)
397
+ end
398
+ bytes.writeUInt8(0, -1)
399
+ append(bytes)
400
+ return len + 1
401
+ end
402
+ def writeOLI()
403
+ if @stringIndex.length === 0
404
+ return self
405
+ end
406
+ @OLI = LEON::gather_layouts(@payload, @stringIndex)
407
+ if @OLI.length === 0
408
+ writeValue(0xFF, Constants::UNSIGNED_CHAR, true)
409
+ return self
410
+ end
411
+ @OLItype = LEON::type_check(@OLI.length)
412
+ writeValue(@OLI.length, @OLItype)
413
+ @OLI.each { |v|
414
+ type = LEON::type_check(v.length)
415
+ writeValue(v.length, type)
416
+ v.each { |v|
417
+ writeValue(v, @stringIndexType, true)
418
+ }
419
+ }
420
+ return self
421
+ end
422
+ def writeSI()
423
+ @stringIndex = LEON::gather_strings(@payload)
424
+ if @stringIndex.length === 0
425
+ writeValue(0xFF, Constants::UNSIGNED_CHAR, true)
426
+ return self
427
+ end
428
+ @stringIndexType = LEON::type_check(@stringIndex.length)
429
+ writeValue(@stringIndex.length, @stringIndexType)
430
+ @stringIndex.each { |v|
431
+ writeString(v)
432
+ }
433
+ return self
434
+ end
435
+ end
436
+ def self.match_layout(val, stringIndex, oli)
437
+ keys = val.keys
438
+ layout = Array.new
439
+ for i in 0..(keys.length - 1)
440
+ if keys[i].kind_of? Symbol
441
+ keys[i] = keys[i].to_s
442
+ end
443
+ layout.push stringIndex.index(keys[i])
444
+ end
445
+ layout.sort! { |a, b|
446
+ a <=> b
447
+ }
448
+ i = 0
449
+ while i < oli.length
450
+ if layout.eql? oli[i].sort { |a, b| a <=> b }
451
+ return i
452
+ end
453
+ i += 1
454
+ end
455
+ end
456
+ def self.gather_layouts(*args)
457
+ if args.length > 3
458
+ branch = args[3]
459
+ else
460
+ branch = args[0]
461
+ end
462
+ if args.length > 2
463
+ ret = args[2]
464
+ else
465
+ ret = Array.new
466
+ end
467
+ val = args[0]
468
+ stringIndex = args[1]
469
+ if branch.kind_of? Array
470
+ branch.each { |v|
471
+ LEON::gather_layouts(val, stringIndex, ret, v)
472
+ }
473
+ elsif branch.kind_of? Hash
474
+ ret.push Array.new
475
+ branch.each { |k, v|
476
+ if k.kind_of? Symbol
477
+ k = k.to_s
478
+ end
479
+ ret[ret.length - 1].push stringIndex.index(k)
480
+ }
481
+ branch.each { |k, v|
482
+ LEON::gather_layouts(val, stringIndex, ret, v)
483
+ }
484
+ end
485
+ return ret
486
+ end
487
+ def self.gather_strings(*args)
488
+ if args.length > 2
489
+ branch = args[2]
490
+ else
491
+ branch = args[0]
492
+ end
493
+ if args.length > 1
494
+ ret = args[1]
495
+ else
496
+ ret = Array.new
497
+ end
498
+ val = args[0]
499
+ if branch.kind_of? Array
500
+ branch.each { |v|
501
+ LEON::gather_strings(val, ret, v)
502
+ }
503
+ elsif branch.kind_of? Hash
504
+ branch.each { |k, v|
505
+ if k.kind_of? Symbol
506
+ k = k.to_s
507
+ end
508
+ set_push(ret, k)
509
+ }
510
+ branch.each { |k, v|
511
+ LEON::gather_strings(val, ret, v)
512
+ }
513
+ elsif branch.kind_of? String
514
+ set_push(ret, branch)
515
+ elsif branch.kind_of? Symbol
516
+ set_push(ret, branch.to_s)
517
+ end
518
+ return ret
519
+ end
520
+ def self.set_push(arr, v)
521
+ if !arr.include? v
522
+ arr.push v
523
+ end
524
+ end
525
+ end
data/lib/leon.rb ADDED
@@ -0,0 +1,28 @@
1
+ require 'constants'
2
+ require 'string-buffer'
3
+ require 'io'
4
+ module LEON
5
+ include Constants
6
+ class Channel
7
+ def initialize(spec)
8
+ @spec = spec
9
+ end
10
+ def generate(payload)
11
+ return Encoder.new(payload, @spec).writeData().export()
12
+ end
13
+ def parse(payload)
14
+ Parser.new(StringBuffer.new(payload), @spec).parseValueWithSpec()
15
+ end
16
+ end
17
+ def self.parse(str)
18
+ Parser.new(StringBuffer.new(str)).parseSI().parseOLI().parseValue()
19
+ end
20
+ def self.generate(payload)
21
+ Encoder.new(payload).writeSI().writeOLI().writeData().export()
22
+ end
23
+ end
24
+ class Object
25
+ def to_leon()
26
+ LEON::generate(self)
27
+ end
28
+ end
@@ -0,0 +1,319 @@
1
+ require 'constants'
2
+
3
+ module LEON
4
+ class StringBuffer
5
+ attr_accessor :buffer
6
+ def self.bytes(v, type)
7
+ ret = Array.new
8
+ if type === Constants::UNSIGNED_CHAR
9
+ ret.push v
10
+ return ret
11
+ end
12
+ if type === Constants::CHAR
13
+ return v < 0 ? StringBuffer.bytes(complement(-v, 8), Constants::UNSIGNED_CHAR) : StringBuffer.bytes(v, Constants::UNSIGNED_CHAR)
14
+ end
15
+ if type === Constants::UNSIGNED_SHORT
16
+ ret.push(v >> 8)
17
+ ret.push(v & 0xFF)
18
+ return ret
19
+ end
20
+ if type === Constants::SHORT
21
+ return v < 0 ? StringBuffer.bytes(complement(-v, 16), Constants::UNSIGNED_SHORT) : StringBuffer.bytes(v, Constants::UNSIGNED_SHORT)
22
+ end
23
+ if type === Constants::UNSIGNED_INT
24
+ ret.push(v >> 24)
25
+ ret.push((v >> 16) & 0xFF)
26
+ ret.push((v >> 8) & 0xFF)
27
+ ret.push(v & 0xFF)
28
+ return ret
29
+ end
30
+ if type === Constants::INT
31
+ return v < 0 ? StringBuffer.bytes(complement(-v, 32), Constants::UNSIGNED_INT) : StringBuffer.bytes(v, Constants::UNSIGNED_INT)
32
+ end
33
+ if type === Constants::FLOAT
34
+ exp = 127
35
+ if v < 0
36
+ sign = 1
37
+ else
38
+ sign = 0
39
+ end
40
+ v = v.abs
41
+ log = Math::log(v)/Math::log(2)
42
+ if log < 0
43
+ log = log.ceil
44
+ else
45
+ log = log.floor
46
+ end
47
+ v *= 2**(-log + 23)
48
+ exp += log
49
+ v = v.round
50
+ v &= 0x7FFFFF
51
+ ret.push(sign << 7)
52
+ ret[0] |= ((exp & 0xFE) >> 1)
53
+ ret.push((exp & 0x01) << 7)
54
+ ret[1] |= ((v >> 16) & 0x7F)
55
+ ret.push((v >> 8) & 0xFF)
56
+ ret.push(v & 0xFF)
57
+ return ret
58
+ end
59
+ if type === Constants::DOUBLE
60
+ exp = 1023
61
+ if v < 0
62
+ sign = 1
63
+ else
64
+ sign = 0
65
+ end
66
+ v = v.abs
67
+ log = Math::log(v)/Math::log(2)
68
+ if log < 0
69
+ log = log.ceil
70
+ else
71
+ log = log.floor
72
+ end
73
+ v *= 2**(-log + 52)
74
+ exp += log
75
+ str = v.to_int.to_s(2)
76
+ v = str[1..-1].to_i(2)
77
+ ret.push(sign << 7)
78
+ ret[0] |= (exp >> 4)
79
+ ret.push((exp & 0x0F) << 4)
80
+ ret[1] |= ((v*2**(-48)).floor & 0x0F)
81
+ sh = 40
82
+ for i in 0..5
83
+ ret.push((v*2**(-sh)).floor & 0xFF)
84
+ sh -= 8
85
+ end
86
+ return ret
87
+ end
88
+ end
89
+ def self.bytes_to_float(bytes)
90
+ sign = (0x80 & bytes[0]) >> 7
91
+ exp = ((bytes[0] & 0x7F) << 1) | ((bytes[1] & 0x80) >> 7)
92
+ sig = 0
93
+ bytes[1] &= 0x7F
94
+ for i in 0..2
95
+ sig |= bytes[1 + i]*2**((2 - i)*8)
96
+ end
97
+ sig |= 0x800000
98
+ return ((sign === 1 ? -sig : sig)*2**(exp - (127 + 23))).to_f
99
+ end
100
+ def self.bytes_to_double(bytes)
101
+ sign = (0x80 & bytes[0]) >> 7
102
+ exp = ((bytes[0] & 0x7F) << 4) | ((bytes[1] & 0xF0) >> 4)
103
+ sig = 0
104
+ bytes[1] &= 0x0F
105
+ for i in 0..6
106
+ sig += bytes[i + 1]*2**((6 - i)*8)
107
+ end
108
+ sig += 0x10000000000000
109
+ return ((sign === 1 ? -sig : sig)*2**(exp - (1023 + 52))).to_f
110
+ end
111
+ def self.complement(v, bits)
112
+ return (v ^ ((1 << bits) - 1)) + 1
113
+ end
114
+ def initialize(*args)
115
+ if args.length > 0
116
+ @buffer = args[0]
117
+ else
118
+ @buffer = ''
119
+ end
120
+ end
121
+ def self.concat(arr)
122
+ return arr.reduce(self.new) { |r, v|
123
+ r.buffer += v.buffer
124
+ r
125
+ }
126
+ end
127
+ def writeUInt8(v, i)
128
+ if i === -1 or i >= @buffer.length
129
+ @buffer += v.chr
130
+ else
131
+ @buffer = @buffer[0..i] + v.chr + @buffer[(i+1)..-1]
132
+ end
133
+ return i + 1
134
+ end
135
+ def writeInt8(v, i)
136
+ v = (v < 0 ? complement(-v, 8) : v)
137
+ return writeUInt8(v, i)
138
+ end
139
+ def writeUInt16LE(v, i)
140
+ bytez = StringBuffer.bytes(v, Constants::UNSIGNED_SHORT)
141
+ add = ''
142
+ bytez.reverse_each { |v|
143
+ add += "#{v.chr}"
144
+ }
145
+ if i >= @buffer.length or i === -1
146
+ @buffer += add
147
+ else
148
+ @buffer = @buffer[0..i] + add + @buffer[(i + 2)..-1]
149
+ end
150
+ return i + 2
151
+ end
152
+ def writeUInt16BE(v, i)
153
+ bytez = StringBuffer.bytes(v, Constants::UNSIGNED_SHORT)
154
+ add = ''
155
+ bytez.each { |v|
156
+ add += "#{v.chr}"
157
+ }
158
+ if i >= @buffer.length or i === -1
159
+ @buffer += add
160
+ else
161
+ @buffer = @buffer[0..i] + add + @buffer[(i + 2)..-1]
162
+ end
163
+ return i + 2
164
+ end
165
+ def writeInt16LE(v, i)
166
+ v = (v < 0 ? complement(-v, 16) : v)
167
+ return writeUInt16LE(v)
168
+ end
169
+ def writeInt16BE(v, i)
170
+ v = (v < 0 ? complement(-v, 16) : v)
171
+ return writeUInt16BE(v)
172
+ end
173
+ def writeUInt32LE(v, i)
174
+ bytez = StringBuffer.bytes(v, Constants::UNSIGNED_INT)
175
+ add = ''
176
+ bytez.reverse_each { |v|
177
+ add += "#{v.chr}"
178
+ }
179
+ if i >= @buffer.length or i === -1
180
+ @buffer += add
181
+ else
182
+ @buffer = @buffer[0..i] + add + @buffer[(i + 4)..-1]
183
+ end
184
+ return i + 4
185
+ end
186
+ def writeUInt32BE(v, i)
187
+ bytez = StringBuffer.bytes(v, Constants::UNSIGNED_INT)
188
+ add = ''
189
+ bytez.each { |v|
190
+ add += "#{v.chr}"
191
+ }
192
+ if i >= @buffer.length or i === -1
193
+ @buffer += add
194
+ else
195
+ @buffer = @buffer[0..i] + add + @buffer[(i + 4)..-1]
196
+ end
197
+ return i + 4
198
+ end
199
+ def writeInt32LE(v, i)
200
+ v = (v < 0 ? complement(-v, i) : v)
201
+ return writeUInt32LE(v)
202
+ end
203
+ def writeInt32BE(v, i)
204
+ v = (v < 0 ? complement(-v, i) : v)
205
+ return writeUInt32BE(v)
206
+ end
207
+ def writeFloatLE(v, i)
208
+ bytez = StringBuffer.bytes(v, Constants::FLOAT)
209
+ bytez.to_enum.with_index.reverse_each { |v, idx|
210
+ writeUInt8(v, i + (3 - idx))
211
+ }
212
+ return i + 4
213
+ end
214
+ def writeFloatBE(v, i)
215
+ bytez = StringBuffer.bytes(v, Constants::FLOAT)
216
+ bytez.to_enum.with_index.each { |v, idx|
217
+ writeUInt8(v, i + idx)
218
+ }
219
+ return i + 4
220
+ end
221
+ def writeDoubleLE(v, i)
222
+ bytez = StringBuffer.bytes(v, Constants::DOUBLE)
223
+ bytez.to_enum.with_index.reverse_each { |v, idx|
224
+ writeUInt8(v, i + (7 - idx))
225
+ }
226
+ return i + 8
227
+ end
228
+ def writeDoubleBE(v, i)
229
+ bytez = StringBuffer.bytes(v, Constants::DOUBLE)
230
+ bytez.to_enum.with_index.each { |v, idx|
231
+ writeUInt8(v, i + idx)
232
+ }
233
+ return i + 8
234
+ end
235
+ def readUInt8(i)
236
+ return @buffer[i].ord
237
+ end
238
+ def readInt8(i)
239
+ v = readUInt8(i)
240
+ if (0x80 & v) != 0
241
+ return -complement(v, 8)
242
+ end
243
+ return v
244
+ end
245
+ def readUInt16LE(i)
246
+ return @buffer[i].ord | (@buffer[i + 1].ord << 8)
247
+ end
248
+ def readUInt16BE(i)
249
+ return (@buffer[i].ord << 8) | @buffer[i + 1].ord
250
+ end
251
+ def readInt16LE(i)
252
+ v = readUInt16LE(i)
253
+ if (v & 0x8000) != 0
254
+ return -complement(v, 16)
255
+ end
256
+ return v
257
+ end
258
+ def readInt16BE(i)
259
+ v = readUInt16BE(i)
260
+ if (v & 0x8000) != 0
261
+ return -complement(v, 16)
262
+ end
263
+ return v
264
+ end
265
+ def readUInt32LE(i)
266
+ return @buffer[i].ord | (@buffer[i + 1].ord << 8) | (@buffer[i + 2].ord << 16) | (@buffer[i + 3].ord << 24)
267
+ end
268
+ def readUInt32BE(i)
269
+ return (@buffer[i].ord << 24) | (@buffer[i + 1].ord << 16) | (@buffer[i + 2].ord << 8) | @buffer[i + 3].ord
270
+ end
271
+ def readInt32LE(i)
272
+ v = readUInt32LE(i)
273
+ if (v & 0x80000000) != 0
274
+ return -complement(v, 32)
275
+ end
276
+ return v
277
+ end
278
+ def readInt32BE(i)
279
+ v = readUInt32BE(i)
280
+ if (v & 0x80000000) != 0
281
+ return -complement(v, 32)
282
+ end
283
+ return v
284
+ end
285
+ def readFloatLE(i)
286
+ bytez = Array.new
287
+ for j in 0..3
288
+ bytez.push readUInt8(i + j)
289
+ end
290
+ bytez.reverse!
291
+ return StringBuffer.bytes_to_float(bytez)
292
+ end
293
+ def readFloatBE(i)
294
+ bytez = Array.new
295
+ for j in 0..3
296
+ bytez.push readUInt8(i + j)
297
+ end
298
+ return StringBuffer.bytes_to_float(bytez)
299
+ end
300
+ def readDoubleLE(i)
301
+ bytez = Array.new
302
+ for j in 0..7
303
+ bytez.push readUInt8(i + j)
304
+ end
305
+ bytez.reverse!
306
+ return StringBuffer.bytes_to_double(bytez)
307
+ end
308
+ def readDoubleBE(i)
309
+ bytez = Array.new
310
+ for j in 0..7
311
+ bytez.push readUInt8(i + j)
312
+ end
313
+ return StringBuffer.bytes_to_double(bytez)
314
+ end
315
+ def toString()
316
+ return @buffer
317
+ end
318
+ end
319
+ end
data/lib/types.rb ADDED
@@ -0,0 +1,21 @@
1
+ module LEON
2
+ class Undefined
3
+ end
4
+ class NaN
5
+ end
6
+ class RegExp
7
+ attr_accessor :pattern
8
+ attr_accessor :modifier
9
+ def initialize(*args)
10
+ if args.length > 1
11
+ @modifier = args[1]
12
+ else
13
+ @modifier = ''
14
+ end
15
+ @pattern = args[0]
16
+ end
17
+ def to_s()
18
+ return '/' + @pattern + '/' + @modifier
19
+ end
20
+ end
21
+ end
metadata ADDED
@@ -0,0 +1,52 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: leon
3
+ version: !ruby/object:Gem::Version
4
+ version: 1.0.0
5
+ prerelease:
6
+ platform: ruby
7
+ authors:
8
+ - Raymond Pulver IV
9
+ autorequire:
10
+ bindir: bin
11
+ cert_chain: []
12
+ date: 2015-07-19 00:00:00.000000000 Z
13
+ dependencies: []
14
+ description: Serialize and deserialize all JavaScript data types to a more compact
15
+ format than JSON that can be dealt with in the browser.
16
+ email: raymond.pulver_iv@uconn.edu
17
+ executables: []
18
+ extensions: []
19
+ extra_rdoc_files: []
20
+ files:
21
+ - lib/buffer-iterator.rb
22
+ - lib/io.rb
23
+ - lib/string-buffer.rb
24
+ - lib/constants.rb
25
+ - lib/leon.rb
26
+ - lib/types.rb
27
+ homepage: http://github.com/raypulver/ruby-leon
28
+ licenses:
29
+ - MIT
30
+ post_install_message:
31
+ rdoc_options: []
32
+ require_paths:
33
+ - lib
34
+ required_ruby_version: !ruby/object:Gem::Requirement
35
+ none: false
36
+ requirements:
37
+ - - ! '>='
38
+ - !ruby/object:Gem::Version
39
+ version: '0'
40
+ required_rubygems_version: !ruby/object:Gem::Requirement
41
+ none: false
42
+ requirements:
43
+ - - ! '>='
44
+ - !ruby/object:Gem::Version
45
+ version: '0'
46
+ requirements: []
47
+ rubyforge_project:
48
+ rubygems_version: 1.8.23
49
+ signing_key:
50
+ specification_version: 3
51
+ summary: LEON serialization for Ruby.
52
+ test_files: []