kingpong-bitwise_string_ops 0.1.2 → 0.1.3

Sign up to get free protection for your applications and to get access to all the features.
data/README.rdoc CHANGED
@@ -23,7 +23,7 @@ The operation is applied to each successive byte (not necessarily
23
23
  character) in the source strings in parallel. For example, the result
24
24
  of "AB" & "CD" is ("A" & "C") + ("B" & "D").
25
25
 
26
- If the operands to a binary bitwise op are strings of different sizes,
26
+ If the operands to a binary bitwise op are strings of different sizes, |
27
27
  and ^ ops act as though the shorter operand had additional zero bits on
28
28
  the right, while the & op acts as though the longer operand were
29
29
  truncated to the length of the shorter. The granularity for such
@@ -67,7 +67,6 @@ AND truncates to the shorter of the two:
67
67
 
68
68
  = Known Issues
69
69
 
70
- * Largely untested
71
70
  * Completely untested with non-string rhs operands
72
71
 
73
72
  = Author
data/Rakefile CHANGED
@@ -3,7 +3,7 @@ require 'rake'
3
3
  require 'echoe'
4
4
 
5
5
  project = "bitwise_string_ops"
6
- version = "0.1.2"
6
+ version = "0.1.3"
7
7
 
8
8
  Echoe.new(project, version) do |p|
9
9
  p.description = "Bitwise operations for Ruby strings"
@@ -2,23 +2,23 @@
2
2
 
3
3
  Gem::Specification.new do |s|
4
4
  s.name = %q{bitwise_string_ops}
5
- s.version = "0.1.2"
5
+ s.version = "0.1.3"
6
6
 
7
7
  s.required_rubygems_version = Gem::Requirement.new(">= 1.2") if s.respond_to? :required_rubygems_version=
8
8
  s.authors = ["Philip Garrett"]
9
- s.date = %q{2009-08-22}
9
+ s.date = %q{2009-08-23}
10
10
  s.description = %q{Bitwise operations for Ruby strings}
11
11
  s.email = %q{philip@pastemagazine.com}
12
12
  s.extensions = ["ext/extconf.rb"]
13
13
  s.extra_rdoc_files = ["CHANGELOG", "ext/bitwise.c", "ext/bitwise_string_ops.c", "ext/bitwise_string_ops.h", "ext/extconf.rb", "lib/bitwise_string_ops.rb", "README.rdoc"]
14
- s.files = ["bitwise_string_ops.gemspec", "CHANGELOG", "ext/bitwise.c", "ext/bitwise_string_ops.c", "ext/bitwise_string_ops.h", "ext/extconf.rb", "init.rb", "lib/bitwise_string_ops.rb", "Manifest", "Rakefile", "README.rdoc", "setup.rb", "test/test.rb", "test/test_helper.rb", "test/test_string_and.rb", "test/test_string_not.rb", "test/test_string_or.rb", "test/test_string_xor.rb"]
14
+ s.files = ["bitwise_string_ops.gemspec", "CHANGELOG", "ext/bitwise.c", "ext/bitwise_string_ops.c", "ext/bitwise_string_ops.h", "ext/extconf.rb", "init.rb", "lib/bitwise_string_ops.rb", "Manifest", "Rakefile", "README.rdoc", "setup.rb", "test/test.rb", "test/test_helper.rb", "test/test_string_and.rb", "test/test_string_not.rb", "test/test_string_or.rb", "test/test_string_xor.rb", "test/test_perl_equivalence.rb"]
15
15
  s.homepage = %q{http://github.com/kingpong/bitwise_string_ops}
16
16
  s.rdoc_options = ["--line-numbers", "--inline-source", "--title", "Bitwise_string_ops", "--main", "README.rdoc"]
17
17
  s.require_paths = ["lib", "ext"]
18
18
  s.rubyforge_project = %q{bitwise_string_ops}
19
19
  s.rubygems_version = %q{1.3.3}
20
- s.summary = %q{bitwise_string_ops 0.1.2}
21
- s.test_files = ["test/test_helper.rb", "test/test_string_and.rb", "test/test_string_not.rb", "test/test_string_or.rb", "test/test_string_xor.rb"]
20
+ s.summary = %q{bitwise_string_ops 0.1.3}
21
+ s.test_files = ["test/test_helper.rb", "test/test_perl_equivalence.rb", "test/test_string_and.rb", "test/test_string_not.rb", "test/test_string_or.rb", "test/test_string_xor.rb"]
22
22
 
23
23
  if s.respond_to? :specification_version then
24
24
  current_version = Gem::Specification::CURRENT_SPECIFICATION_VERSION
@@ -29,6 +29,7 @@
29
29
 
30
30
  // Defining a space for information and references about the module to be stored internally
31
31
  VALUE BitwiseStringOps = Qnil;
32
+ static ID ToString;
32
33
 
33
34
  // Prototype for the initialization method - Ruby calls this, not you
34
35
  void Init_bitwise_string_ops();
@@ -39,21 +40,32 @@ VALUE method_bit_xor(VALUE self, VALUE other);
39
40
  VALUE method_bit_and(VALUE self, VALUE other);
40
41
  VALUE method_bit_not(VALUE self);
41
42
 
43
+ static VALUE to_s(VALUE o);
44
+
42
45
  // The initialization method for this module
43
46
  void Init_bitwise_string_ops()
44
47
  {
45
48
  BitwiseStringOps = rb_define_module("BitwiseStringOps");
46
- rb_define_method(BitwiseStringOps, "bit_or", method_bit_or, 1);
47
- rb_define_method(BitwiseStringOps, "bit_xor", method_bit_xor, 1);
48
- rb_define_method(BitwiseStringOps, "bit_and", method_bit_and, 1);
49
- rb_define_method(BitwiseStringOps, "bit_not", method_bit_not, 0);
49
+ ToString = rb_intern("to_s");
50
+ rb_define_method(BitwiseStringOps, "|", method_bit_or, 1);
51
+ rb_define_method(BitwiseStringOps, "^", method_bit_xor, 1);
52
+ rb_define_method(BitwiseStringOps, "&", method_bit_and, 1);
53
+ rb_define_method(BitwiseStringOps, "~", method_bit_not, 0);
54
+ }
55
+
56
+ static VALUE to_s(VALUE o)
57
+ {
58
+ return rb_obj_is_kind_of(o,rb_cString)
59
+ ? o : rb_funcall(o, ToString, 0);
50
60
  }
51
61
 
52
62
  VALUE method_bit_or(VALUE self, VALUE other)
53
63
  {
54
- VALUE left = StringValue(self), right = StringValue(other);
55
- VALUE dest = rb_str_new(NULL,
56
- string_bitwise_or_result_len(RSTRING(left)->len,
64
+ VALUE left, right, right_s, dest;
65
+ left = StringValue(self);
66
+ right_s = to_s(other);
67
+ right = StringValue(right_s);
68
+ dest = rb_str_new(NULL, string_bitwise_or_result_len(RSTRING(left)->len,
57
69
  RSTRING(right)->len));
58
70
  string_bitwise_or(RSTRING(left)->ptr, RSTRING(left)->len,
59
71
  RSTRING(right)->ptr, RSTRING(right)->len,
@@ -63,9 +75,11 @@ VALUE method_bit_or(VALUE self, VALUE other)
63
75
 
64
76
  VALUE method_bit_xor(VALUE self, VALUE other)
65
77
  {
66
- VALUE left = StringValue(self), right = StringValue(other);
67
- VALUE dest = rb_str_new(NULL,
68
- string_bitwise_xor_result_len(RSTRING(left)->len,
78
+ VALUE left, right, right_s, dest;
79
+ left = StringValue(self);
80
+ right_s = to_s(other);
81
+ right = StringValue(right_s);
82
+ dest = rb_str_new(NULL, string_bitwise_xor_result_len(RSTRING(left)->len,
69
83
  RSTRING(right)->len));
70
84
  string_bitwise_xor(RSTRING(left)->ptr, RSTRING(left)->len,
71
85
  RSTRING(right)->ptr, RSTRING(right)->len,
@@ -75,9 +89,11 @@ VALUE method_bit_xor(VALUE self, VALUE other)
75
89
 
76
90
  VALUE method_bit_and(VALUE self, VALUE other)
77
91
  {
78
- VALUE left = StringValue(self), right = StringValue(other);
79
- VALUE dest = rb_str_new(NULL,
80
- string_bitwise_and_result_len(RSTRING(left)->len,
92
+ VALUE left, right, right_s, dest;
93
+ left = StringValue(self);
94
+ right_s = to_s(other);
95
+ right = StringValue(right_s);
96
+ dest = rb_str_new(NULL, string_bitwise_and_result_len(RSTRING(left)->len,
81
97
  RSTRING(right)->len));
82
98
  string_bitwise_and(RSTRING(left)->ptr, RSTRING(left)->len,
83
99
  RSTRING(right)->ptr, RSTRING(right)->len,
@@ -13,8 +13,4 @@
13
13
  require 'bitwise_string_ops.so'
14
14
  class String
15
15
  include BitwiseStringOps
16
- alias :| :bit_or
17
- alias :^ :bit_xor
18
- alias :& :bit_and
19
- alias :~ :bit_not
20
16
  end
@@ -0,0 +1,79 @@
1
+ #!/usr/bin/env ruby
2
+ require 'test/unit'
3
+ require 'test/test_helper'
4
+ require 'bitwise_string_ops'
5
+
6
+ class TestPerlEquivalence < Test::Unit::TestCase
7
+
8
+ PATH_SEP = RUBY_PLATFORM =~ /mswin/i ? ";" : ":"
9
+ GENERATOR = File.join(File.dirname(__FILE__),"testcases.pl")
10
+
11
+ def test_perl_equivalence
12
+ return unless perl = find_perl
13
+ pipe_reader(perl, GENERATOR) do |pipe|
14
+ while op = read_string(pipe)
15
+ case op
16
+ when "|"
17
+ result, left, right = read_strings(pipe,3)
18
+ assert_equal left | right, result
19
+ when "^"
20
+ result, left, right = read_strings(pipe,3)
21
+ assert_equal left ^ right, result
22
+ when "&"
23
+ result, left, right = read_strings(pipe,3)
24
+ assert_equal left & right, result
25
+ when "~"
26
+ result, operand = read_strings(pipe,2)
27
+ assert_equal ~operand, result
28
+ end
29
+ end
30
+ end
31
+ end
32
+
33
+ private
34
+
35
+ def find_perl
36
+ ENV["PATH"].split(PATH_SEP).
37
+ map {|path| File.join(path,"perl") }.
38
+ find {|perl| File.executable?(perl) }
39
+ end
40
+
41
+ # Runs a command and yields an IO object opened for reading from the command.
42
+ # Does *NOT* do any shell expansion (that's the point).
43
+ # +args+ should be [program,arg1,...]
44
+ def pipe_reader(*args)
45
+ # avoid shell expansion using fork/exec
46
+ reader, writer = IO.pipe
47
+ pid = fork
48
+ if pid
49
+ writer.close
50
+ yield(reader)
51
+ Process.waitpid(pid)
52
+ else
53
+ begin
54
+ reader.close
55
+ STDIN.reopen("/dev/null")
56
+ STDOUT.reopen(writer)
57
+ exec(*args)
58
+ rescue => e
59
+ # prevent child from jumping out of this scope and continuing main program
60
+ STDERR.puts(e.to_s)
61
+ end
62
+ exit! # will only reach here if exec() failed
63
+ end
64
+ end
65
+
66
+ def read_string(io)
67
+ length = io.read(4).unpack("N").first
68
+ io.read(length)
69
+ rescue => e
70
+ io.eof? ? nil : raise(e)
71
+ end
72
+
73
+ def read_strings(io,n)
74
+ ret = []
75
+ n.times { ret << read_string(io) }
76
+ ret
77
+ end
78
+
79
+ end
@@ -5,6 +5,37 @@ require 'bitwise_string_ops'
5
5
 
6
6
  class TestStringAnd < Test::Unit::TestCase
7
7
 
8
+ def test_empty
9
+ assert_equal "" & "", ""
10
+ end
11
+
12
+ def test_single
13
+ assert_equal "0" & "1", "0"
14
+ assert_equal "a" & "A", "A"
15
+ end
16
+
17
+ def test_multiple
18
+ assert_equal "01" & "10", "00"
19
+ assert_equal "aB" & "Ab", "AB"
20
+ end
21
+
22
+ def test_overflow
23
+ assert_equal "111" & "00", "00"
24
+ assert_equal "00" & "111", "00"
25
+ end
26
+
27
+ def test_non_string
28
+ assert_equal "1" & 1, "1" & "1"
29
+ assert_equal "10" & 1, "10" & "1"
30
+ end
31
+
32
+ def test_truth_table
33
+ assert_equal "0" & "0", "0"
34
+ assert_equal "0" & "1", "0"
35
+ assert_equal "1" & "0", "0"
36
+ assert_equal "1" & "1", "1"
37
+ end
38
+
8
39
  def test_perldoc
9
40
  assert_equal "japh\nJunk" & "_____", "JAPH\n"
10
41
  end
@@ -5,6 +5,20 @@ require 'bitwise_string_ops'
5
5
 
6
6
  class TestStringNot < Test::Unit::TestCase
7
7
 
8
+ def test_empty
9
+ assert_equal "" & "", ""
10
+ end
11
+
12
+ def test_single
13
+ assert_equal ~"1", "\316"
14
+ assert_equal ~"a", "\236"
15
+ end
16
+
17
+ def test_multiple
18
+ assert_equal ~"01", "\317\316"
19
+ assert_equal ~"aB", "\236\275"
20
+ end
21
+
8
22
  def test_perldoc
9
23
  assert_equal ~"japh", "\225\236\217\227"
10
24
  end
@@ -5,6 +5,38 @@ require 'bitwise_string_ops'
5
5
 
6
6
  class TestStringOr < Test::Unit::TestCase
7
7
 
8
+ def test_empty
9
+ assert_equal "" | "", ""
10
+ end
11
+
12
+ def test_single
13
+ assert_equal "0" | "1", "1"
14
+ assert_equal "a" | "A", "a"
15
+ end
16
+
17
+ def test_multiple
18
+ assert_equal "01" | "10", "11"
19
+ assert_equal "aB" | "Ab", "ab"
20
+ end
21
+
22
+ def test_overflow
23
+ assert_equal "111" | "00", "111"
24
+ assert_equal "00" | "111", "111"
25
+ end
26
+
27
+ def test_non_string
28
+ assert_equal "1" | 1, "1" | "1"
29
+ assert_equal "10" | 1, "10" | "1"
30
+ end
31
+
32
+ def test_truth_table
33
+ assert_equal "0" | "0", "0"
34
+ assert_equal "0" | "1", "1"
35
+ assert_equal "1" | "0", "1"
36
+ assert_equal "1" | "1", "1"
37
+ end
38
+
39
+ # superficial test for perl equivalency
8
40
  def test_perldoc
9
41
  assert_equal "JA" | " ph\n", "japh\n"
10
42
  end
@@ -5,6 +5,37 @@ require 'bitwise_string_ops'
5
5
 
6
6
  class TestStringXor < Test::Unit::TestCase
7
7
 
8
+ def test_empty
9
+ assert_equal "" ^ "", ""
10
+ end
11
+
12
+ def test_single
13
+ assert_equal "0" ^ "1", "\001"
14
+ assert_equal "a" ^ "A", " "
15
+ end
16
+
17
+ def test_multiple
18
+ assert_equal "01" ^ "10", "\001\001"
19
+ assert_equal "aB" ^ "Ab", " "
20
+ end
21
+
22
+ def test_reversible
23
+ orig = "abc"
24
+ mask = "def"
25
+ assert_not_equal orig ^ mask, orig
26
+ assert_equal( (orig ^ mask) ^ mask, orig)
27
+ end
28
+
29
+ def test_non_string
30
+ assert_equal "1" ^ 1, "1" ^ "1"
31
+ assert_equal "10" ^ 1, "10" ^ "1"
32
+ end
33
+
34
+ def test_overflow
35
+ assert_equal "111" ^ "00", "\001\0011"
36
+ assert_equal "00" ^ "111", "\001\0011"
37
+ end
38
+
8
39
  def test_perldoc
9
40
  assert_equal "j p \n" ^ " a h", "JAPH\n"
10
41
  end
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: kingpong-bitwise_string_ops
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.1.2
4
+ version: 0.1.3
5
5
  platform: ruby
6
6
  authors:
7
7
  - Philip Garrett
@@ -9,7 +9,7 @@ autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
11
 
12
- date: 2009-08-22 00:00:00 -07:00
12
+ date: 2009-08-23 00:00:00 -07:00
13
13
  default_executable:
14
14
  dependencies: []
15
15
 
@@ -46,6 +46,7 @@ files:
46
46
  - test/test_string_not.rb
47
47
  - test/test_string_or.rb
48
48
  - test/test_string_xor.rb
49
+ - test/test_perl_equivalence.rb
49
50
  has_rdoc: false
50
51
  homepage: http://github.com/kingpong/bitwise_string_ops
51
52
  licenses:
@@ -78,9 +79,10 @@ rubyforge_project: bitwise_string_ops
78
79
  rubygems_version: 1.3.5
79
80
  signing_key:
80
81
  specification_version: 3
81
- summary: bitwise_string_ops 0.1.2
82
+ summary: bitwise_string_ops 0.1.3
82
83
  test_files:
83
84
  - test/test_helper.rb
85
+ - test/test_perl_equivalence.rb
84
86
  - test/test_string_and.rb
85
87
  - test/test_string_not.rb
86
88
  - test/test_string_or.rb