kingpong-bitwise_string_ops 0.1.2 → 0.1.3

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