bitstream 0.0.1

Sign up to get free protection for your applications and to get access to all the features.
@@ -0,0 +1,37 @@
1
+ # Author:: Natsuki Kawai (natsuki.kawai@gmail.com)
2
+ # Copyright:: Copyright 2011 Natsuki Kawai
3
+ # License:: 2-clause BSDL or Ruby's
4
+
5
+
6
+ module BitStream
7
+
8
+ module Utils
9
+
10
+ def self.bit_lshift(s, bit)
11
+ if bit != 0
12
+ last_byte = nil
13
+ (s.size - 1).times do |i|
14
+ dbyte = s[i..(i + 1)].unpack('n')[0]
15
+ c = dbyte >> (8 - bit)
16
+ s[i] = (c & 0xff).chr
17
+ end
18
+ end
19
+ end
20
+
21
+ def self.bit_rshift(s, bit)
22
+ if bit != 0
23
+ s << "\0"
24
+ first_byte = nil
25
+ (s.size - 1).downto 1 do |i|
26
+ dbyte = s[(i - 1)..i].unpack('n')[0]
27
+ c = dbyte >> bit
28
+ s[i] = (c & 0xff).chr
29
+ first_byte = c >> 8
30
+ end
31
+ s[0] = first_byte.chr
32
+ end
33
+ end
34
+
35
+ end
36
+
37
+ end
@@ -0,0 +1,52 @@
1
+ # Author:: Natsuki Kawai (natsuki.kawai@gmail.com)
2
+ # Copyright:: Copyright 2011 Natsuki Kawai
3
+ # License:: 2-clause BSDL or Ruby's
4
+
5
+
6
+ require 'types/string-utils'
7
+
8
+ module BitStream
9
+
10
+ class String
11
+
12
+ def self.instance(props, byte_len)
13
+ new byte_len
14
+ end
15
+
16
+ def initialize(byte_len)
17
+ @byte_len = byte_len
18
+ end
19
+
20
+ def length
21
+ @byte_len * 8
22
+ end
23
+
24
+ def read(s, offset)
25
+ bitoffset = offset % 8
26
+ head = offset / 8
27
+ tail = (offset + @byte_len * 8 + 7) / 8
28
+ val = s[head...tail]
29
+ Utils.bit_lshift(val, bitoffset)
30
+ val.slice!(val.size - 1) if bitoffset != 0
31
+
32
+ [val, @byte_len * 8]
33
+ end
34
+
35
+ def write(s, offset, data)
36
+ head = offset / 8
37
+ tail = (offset + @byte_len * 8 + 7) / 8
38
+ if offset % 8 != 0
39
+ bitoffset = offset % 8
40
+ Utils.bit_rshift(data, bitoffset)
41
+ s[head] = ((data[0].ord & 0xff >> bitoffset) | (s[head].ord & 0xff << (8 - bitoffset))).chr
42
+ s[tail - 1] = (data[data.size - 1].ord & 0xff << (8 - bitoffset)).chr
43
+ s[(head + 1)..(tail - 2)] = data[1..(data.size - 2)]
44
+ else
45
+ s[head...tail] = data
46
+ end
47
+ return @byte_len * 8
48
+ end
49
+
50
+ end
51
+
52
+ end
@@ -0,0 +1,12 @@
1
+ require_relative 'gzip'
2
+
3
+ gzip = nil
4
+ File.open(ARGV[0], "rb") do |file|
5
+ gzip = Gzip.create(file.read)
6
+ end
7
+
8
+ if gzip.respond_to? :original_file_name
9
+ puts "original_file_name:#{gzip.original_file_name}"
10
+ else
11
+ puts "The gzip does not contain its original file name."
12
+ end
data/sample/gzip.rb ADDED
@@ -0,0 +1,38 @@
1
+ require 'bitstream'
2
+
3
+ class Gzip
4
+
5
+ include BitStream
6
+ byte_order :little_endian
7
+
8
+ FHCRC = 1 << 1
9
+ FEXTRA = 1 << 2
10
+ FNAME = 1 << 3
11
+ FCOMMENT = 1 << 4
12
+
13
+ fields do
14
+ unsigned :id1, 8
15
+ unsigned :id2, 8
16
+ unsigned :cm, 8
17
+ unsigned :flg, 8
18
+ unsigned :mtime, 32
19
+ unsigned :xfl, 8
20
+ unsigned :os, 8
21
+ if (flg & FEXTRA) != 0
22
+ unsigned :xlen, 16
23
+ string :extra_field, xlen
24
+ end
25
+ if (flg & FNAME) != 0
26
+ # cstring means a NULL-terminated string.
27
+ cstring :original_file_name
28
+ end
29
+ if (flg & FCOMMENT) != 0
30
+ # cstring means a NULL-terminated string.
31
+ cstring :file_comment
32
+ end
33
+ if (flg & FHCRC) != 0
34
+ unsigned :crc16, 16
35
+ end
36
+ end
37
+
38
+ end
@@ -0,0 +1,15 @@
1
+ require 'bitstream'
2
+
3
+ class Tar
4
+
5
+ include BitStream
6
+ byte_order :big_endian
7
+
8
+ fields do
9
+ cstring :name
10
+ string :padding1, 99 - file_name.size
11
+ string :mode, 8
12
+ string :uid, 8
13
+ string :gid, 8
14
+ string
15
+ end
@@ -0,0 +1,33 @@
1
+ # Author:: Natsuki Kawai (natsuki.kawai@gmail.com)
2
+ # Copyright:: Copyright 2011 Natsuki Kawai
3
+ # License:: 2-clause BSDL or Ruby's
4
+
5
+
6
+ require 'test/unit'
7
+ require 'bitstream'
8
+
9
+ class ArraySample
10
+
11
+ include BitStream
12
+
13
+ fields do
14
+ array :a1, 5, :unsigned_int, 16
15
+ end
16
+
17
+ end
18
+
19
+ class TestArray < Test::Unit::TestCase
20
+
21
+ def setup
22
+ @spec = ArraySample.create "\x01\x02\x03\x04\x05\x06\x07\x08\x09\x0a"
23
+ end
24
+
25
+ def test_a1
26
+ assert_equal(0x0102, @spec.a1[0])
27
+ assert_equal(0x0304, @spec.a1[1])
28
+ assert_equal(0x0506, @spec.a1[2])
29
+ assert_equal(0x0708, @spec.a1[3])
30
+ assert_equal(0x090a, @spec.a1[4])
31
+ end
32
+
33
+ end
@@ -0,0 +1,50 @@
1
+ # Author:: Natsuki Kawai (natsuki.kawai@gmail.com)
2
+ # Copyright:: Copyright 2011 Natsuki Kawai
3
+ # License:: 2-clause BSDL or Ruby's
4
+
5
+
6
+ require 'test/unit'
7
+ require 'bitstream'
8
+
9
+ class ConditionSample
10
+
11
+ include BitStream
12
+
13
+ fields {
14
+ unsigned_int :u1, 32
15
+ if u1 == 0
16
+ unsigned_int :u2, 32
17
+ end
18
+ }
19
+
20
+ end
21
+
22
+ class TestCondition < Test::Unit::TestCase
23
+
24
+ def setup
25
+ end
26
+
27
+ def test_condition_true
28
+ spec = ConditionSample.create "\x00\x00\x00\x00\x00\x00\x00\x01"
29
+ assert_equal(0, spec.u1)
30
+ assert_equal(1, spec.u2)
31
+ end
32
+
33
+ def test_condition_false
34
+ spec = ConditionSample.create "\x00\x00\x00\x01\x00\x00\x00\x01"
35
+ assert_equal(1, spec.u1)
36
+ assert_raise(NoMethodError) do
37
+ spec.u2
38
+ end
39
+ end
40
+
41
+ def test_condition_false_with_dummy
42
+ ConditionSample.create "\x00\x00\x00\x00\x00\x00\x00\x01" # dummy
43
+ spec = ConditionSample.create "\x00\x00\x00\x01\x00\x00\x00\x01"
44
+ assert_equal(1, spec.u1)
45
+ assert_raise(NoMethodError) do
46
+ spec.u2
47
+ end
48
+ end
49
+
50
+ end
@@ -0,0 +1,34 @@
1
+ # Author:: Natsuki Kawai (natsuki.kawai@gmail.com)
2
+ # Copyright:: Copyright 2011 Natsuki Kawai
3
+ # License:: 2-clause BSDL or Ruby's
4
+
5
+
6
+ require 'test/unit'
7
+ require 'bitstream'
8
+
9
+ class DynArraySample
10
+
11
+ include BitStream
12
+
13
+ fields {
14
+ dyn_array :a1, :char
15
+ while a1.last != "\0"
16
+ dyn_array :a1, :char
17
+ end
18
+ }
19
+
20
+ end
21
+
22
+
23
+ class TestDynArray < Test::Unit::TestCase
24
+
25
+ def setup
26
+ @spec = DynArraySample.create "foobar\0"
27
+ end
28
+
29
+ def test_a1
30
+ assert_equal("foobar\0", @spec.a1.join)
31
+ end
32
+
33
+ end
34
+
@@ -0,0 +1,64 @@
1
+ # Author:: Natsuki Kawai (natsuki.kawai@gmail.com)
2
+ # Copyright:: Copyright 2011 Natsuki Kawai
3
+ # License:: 2-clause BSDL or Ruby's
4
+
5
+
6
+ require 'test/unit'
7
+ require 'bitstream'
8
+
9
+ class Nested
10
+
11
+ include BitStream
12
+
13
+ fields do
14
+ unsigned_int "u1", 8
15
+ unsigned_int :u2, 8
16
+ end
17
+
18
+ end
19
+
20
+ class Nesting
21
+
22
+ include BitStream
23
+
24
+ add_type Nested, :nested
25
+
26
+ fields do
27
+ unsigned_int "u1", 8
28
+ nested "n"
29
+ unsigned_int :u2, 8
30
+ end
31
+
32
+ end
33
+
34
+ class TestNesting < Test::Unit::TestCase
35
+
36
+ def setup
37
+ @spec = Nesting.create "\x01\x02\x03\x04"
38
+ end
39
+
40
+ def test_nesting_u1
41
+ assert_equal(0x01, @spec.u1)
42
+ end
43
+
44
+ def test_nesting_u2
45
+ assert_equal(0x04, @spec.u2)
46
+ end
47
+
48
+ def test_nesting
49
+ assert_equal(32, @spec.length)
50
+ end
51
+
52
+ def test_nested_u1
53
+ assert_equal(0x02, @spec.n.u1)
54
+ end
55
+
56
+ def test_nested_u2
57
+ assert_equal(0x03, @spec.n.u2)
58
+ end
59
+
60
+ def test_nested
61
+ assert_equal(16, @spec.n.length)
62
+ end
63
+
64
+ end
@@ -0,0 +1,92 @@
1
+ # Author:: Natsuki Kawai (natsuki.kawai@gmail.com)
2
+ # Copyright:: Copyright 2011 Natsuki Kawai
3
+ # License:: 2-clause BSDL or Ruby's
4
+
5
+
6
+ require 'test/unit'
7
+ require 'bitstream'
8
+
9
+ class SimpleIntBe
10
+
11
+ include BitStream
12
+
13
+ byte_order :big_endian
14
+
15
+ fields {
16
+ unsigned_int "u1", 32
17
+ unsigned_int :u2, 32
18
+ cstring "cs1"
19
+ unsigned_int "u3", 1
20
+ unsigned_int "u4", 7
21
+ string :s1, 3
22
+ }
23
+
24
+ end
25
+
26
+ class SimpleIntLe
27
+
28
+ include BitStream
29
+
30
+ byte_order :little_endian
31
+
32
+ fields {
33
+ unsigned_int "u1", 32
34
+ unsigned_int :u2, 32
35
+ cstring "cs1"
36
+ unsigned_int "u3", 1
37
+ unsigned_int "u4", 7
38
+ string :s1, 3
39
+ }
40
+
41
+ end
42
+
43
+ class TestSimpleInt < Test::Unit::TestCase
44
+
45
+ def setup
46
+ @spec = SimpleIntBe.create "\x10\x20\x30\x40\x50\x60\x70\x80foobar\00\xfebazdummy"
47
+
48
+ # dummy
49
+ dummy = SimpleIntBe.create "\x10\x20\x30\x40\x50\x60\x70\x80foobar\00\xfebazdummy"
50
+
51
+ @spec_le = SimpleIntLe.create "\x10\x20\x30\x40\x50\x60\x70\x80foobar\00\xfebazdummy"
52
+ end
53
+
54
+ def test_u1
55
+ assert_equal(0x10203040.to_s(16), @spec.u1.to_s(16))
56
+ end
57
+ def test_u1le
58
+ assert_equal(0x40302010.to_s(16), @spec_le.u1.to_s(16))
59
+ end
60
+
61
+ def test_u2
62
+ assert_equal(0x50607080.to_s(16), @spec.u2.to_s(16))
63
+ end
64
+ def test_u2le
65
+ assert_equal(0x80706050.to_s(16), @spec_le.u2.to_s(16))
66
+ end
67
+
68
+ def test_u3
69
+ assert_equal(1, @spec.u3)
70
+ end
71
+ def test_u3le
72
+ assert_equal(1, @spec_le.u3)
73
+ end
74
+
75
+ def test_u4
76
+ assert_equal(0x7e, @spec.u4)
77
+ end
78
+ def test_u4le
79
+ assert_equal(0x7e, @spec_le.u4)
80
+ end
81
+
82
+ def test_cs1
83
+ assert_equal("foobar", @spec.cs1)
84
+ assert_equal("foobar", @spec_le.cs1)
85
+ end
86
+
87
+ def test_s1
88
+ assert_equal("baz", @spec.s1)
89
+ assert_equal("baz", @spec_le.s1)
90
+ end
91
+
92
+ end
@@ -0,0 +1,34 @@
1
+ # Author:: Natsuki Kawai (natsuki.kawai@gmail.com)
2
+ # Copyright:: Copyright 2011 Natsuki Kawai
3
+ # License:: 2-clause BSDL or Ruby's
4
+
5
+
6
+ require 'test/unit'
7
+ require 'bitstream'
8
+
9
+ class HavingProps
10
+
11
+ include BitStream
12
+
13
+ fields do
14
+ unsigned_int :u1, props[:lengths][0]
15
+ unsigned_int :u2, props[:lengths][1]
16
+ end
17
+
18
+ end
19
+
20
+ class TestSimpleProperties < Test::Unit::TestCase
21
+
22
+ def setup
23
+ @spec = HavingProps.create "\x01\x02\x03\x04", lengths: [24, 8]
24
+ end
25
+
26
+ def test_u1
27
+ assert_equal(0x010203, @spec.u1)
28
+ end
29
+
30
+ def test_u2
31
+ assert_equal(0x04, @spec.u2)
32
+ end
33
+
34
+ end
@@ -0,0 +1,14 @@
1
+ # Author:: Natsuki Kawai (natsuki.kawai@gmail.com)
2
+ # Copyright:: Copyright 2011 Natsuki Kawai
3
+ # License:: 2-clause BSDL or Ruby's
4
+
5
+
6
+ require 'test/test-primitives'
7
+ require 'test/test-array'
8
+ require 'test/test-dynarray'
9
+ require 'test/test-nesting'
10
+ require 'test/test-simple-properties'
11
+ require 'test/types/test-character'
12
+ require 'test/types/test-integer'
13
+ require 'test/types/test-string'
14
+ require 'test/types/test-cstring'
@@ -0,0 +1,19 @@
1
+ # Author:: Natsuki Kawai (natsuki.kawai@gmail.com)
2
+ # Copyright:: Copyright 2011 Natsuki Kawai
3
+ # License:: 2-clause BSDL or Ruby's
4
+
5
+
6
+ require 'test/unit'
7
+ require 'types/character'
8
+
9
+ class TestUint < Test::Unit::TestCase
10
+
11
+ def test_char_nooffset_read
12
+ type = BitStream::Char.instance({})
13
+ val, len = type.read("abcd", 8)
14
+ assert_equal("b", val)
15
+ assert_equal(8, len)
16
+ end
17
+
18
+ end
19
+
@@ -0,0 +1,18 @@
1
+ # Author:: Natsuki Kawai (natsuki.kawai@gmail.com)
2
+ # Copyright:: Copyright 2011 Natsuki Kawai
3
+ # License:: 2-clause BSDL or Ruby's
4
+
5
+
6
+ require 'test/unit'
7
+ require 'types/cstring'
8
+
9
+ class TestCstring < Test::Unit::TestCase
10
+
11
+ def test_aligned_read
12
+ type = BitStream::Cstring.instance({})
13
+ val, len = type.read("foobar\0baz", 16)
14
+ assert_equal("obar", val)
15
+ assert_equal(8 * "obar\0".size, len)
16
+ end
17
+
18
+ end
@@ -0,0 +1,98 @@
1
+ # Author:: Natsuki Kawai (natsuki.kawai@gmail.com)
2
+ # Copyright:: Copyright 2011 Natsuki Kawai
3
+ # License:: 2-clause BSDL or Ruby's
4
+
5
+
6
+ require 'test/unit'
7
+ require 'types/integer'
8
+
9
+ class TestUint < Test::Unit::TestCase
10
+
11
+ BE_PROP = { :byte_order => :big_endian }
12
+ LE_PROP = { :byte_order => :little_endian }
13
+
14
+ def test_uint32be_nooffset_read
15
+ type = BitStream::Unsigned.instance(BE_PROP,32)
16
+ val, len = type.read("\x01\x02\x03\x04", 0)
17
+ assert_equal(0x01020304, val)
18
+ assert_equal(32, len)
19
+ end
20
+
21
+ def test_uint32le_nooffset_read
22
+ type = BitStream::Unsigned.instance(LE_PROP,32)
23
+ val, len = type.read("\x01\x02\x03\x04", 0)
24
+ assert_equal(0x04030201, val)
25
+ assert_equal(32, len)
26
+ end
27
+
28
+ def test_sint32be_nooffset_read
29
+ type = BitStream::Signed.instance(BE_PROP,32)
30
+ val, len = type.read("\xfe\xfd\xfc\xfb", 0)
31
+ assert_equal(-0x01020304 - 1, val)
32
+ assert_equal(32, len)
33
+ end
34
+
35
+ def test_sint32le_nooffset_read
36
+ type = BitStream::Signed.instance(LE_PROP,32)
37
+ val, len = type.read("\xfe\xfd\xfc\xfb", 0)
38
+ assert_equal(-0x04030201 - 1, val)
39
+ assert_equal(32, len)
40
+ end
41
+
42
+ def test_uint32_nooffset_write
43
+ type = BitStream::Unsigned.instance(BE_PROP, 32)
44
+ val = "\xff\x00"
45
+ type.write(val, 8, 0x01020304)
46
+ assert_equal("\xff\x01\x02\x03\x04", val)
47
+ end
48
+
49
+ def test_uint32be_offset4_read
50
+ type = BitStream::Unsigned.instance(BE_PROP, 32)
51
+ val, len = type.read("\xf1\x02\x03\x04\x05", 4)
52
+ assert_equal(0x10203040.to_s(16), val.to_s(16))
53
+ assert_equal(32, len)
54
+ end
55
+
56
+ def test_uint32be_offset1_read
57
+ type = BitStream::Unsigned.instance(BE_PROP, 32)
58
+ val, len = type.read("\x12\x23\x34\x45\x56", 1)
59
+ assert_equal(0x2446688a.to_s(16), val.to_s(16))
60
+ assert_equal(32, len)
61
+ end
62
+
63
+ def test_uint32le_offset4_read
64
+ type = BitStream::Unsigned.instance(LE_PROP, 32)
65
+ val, len = type.read("\xf1\x02\x03\x04\x05", 4)
66
+ assert_equal(0x5040302f.to_s(16), val.to_s(16))
67
+ assert_equal(32, len)
68
+ end
69
+
70
+ def test_uint32le_offset1_read
71
+ type = BitStream::Unsigned.instance(LE_PROP, 32)
72
+ val, len = type.read("\x80\x23\x34\x45\x56", 1)
73
+ assert_equal(0xac8a6847.to_s(16), val.to_s(16))
74
+ assert_equal(32, len)
75
+ end
76
+
77
+ def test_uint1be_read
78
+ type = BitStream::Unsigned.instance(BE_PROP, 1)
79
+ val, len = type.read("\x40", 1)
80
+ assert_equal(1, val)
81
+ assert_equal(1, len)
82
+
83
+ val, len = type.read("\xfd", 6)
84
+ assert_equal(0, val)
85
+ assert_equal(1, len)
86
+ end
87
+
88
+ def test_uint1le_read
89
+ type = BitStream::Unsigned.instance(LE_PROP, 1)
90
+ val, len = type.read("\x40", 1)
91
+ assert_equal(1, val)
92
+ assert_equal(1, len)
93
+
94
+ val, len = type.read("\xfd", 6)
95
+ assert_equal(0, val)
96
+ assert_equal(1, len)
97
+ end
98
+ end
@@ -0,0 +1,41 @@
1
+ # Author:: Natsuki Kawai (natsuki.kawai@gmail.com)
2
+ # Copyright:: Copyright 2011 Natsuki Kawai
3
+ # License:: 2-clause BSDL or Ruby's
4
+
5
+
6
+ require 'test/unit'
7
+ require 'types/string'
8
+
9
+ class TestString < Test::Unit::TestCase
10
+
11
+ def test_aligned_read
12
+ type = BitStream::String.instance({}, 3)
13
+ val, len = type.read("foobarbaz", 16)
14
+ assert_equal("oba", val)
15
+ assert_equal(3 * 8, len)
16
+ end
17
+
18
+ def test_aligned_write
19
+ type = BitStream::String.instance({}, 3)
20
+ val = "foobarbaz"
21
+ ret = type.write(val, 24, "qux")
22
+ assert_equal("fooquxbaz", val)
23
+ end
24
+
25
+ def test_unaligned_read
26
+ type = BitStream::String.instance({}, 2)
27
+ val, len = type.read([0x12345678].pack('N'), 1)
28
+ assert_equal("\x24\x68", val)
29
+ assert_equal(2 * 8, len)
30
+ end
31
+
32
+ def test_unaligned_write
33
+ type = BitStream::String.instance({}, 2)
34
+ val = "\x12\x34"
35
+ ret = type.write(val, 7, "\xcd\xef")
36
+
37
+ assert_equal("\x13\x9b", val[0..1])
38
+ assert(val[2].ord & 0xfe == 0xde)
39
+ end
40
+
41
+ end