bitstream 0.0.1

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,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