leon 1.0.0

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.
@@ -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: []