ruby picture

RCR 222: Add bitwise AND/XOR/OR/NOT for String

Submitted by David Garamond (Thu Feb 26 06:02:26 UTC 2004)

Abstract

Add String#^, #!, #&, and #~ for fast bitwise operations on byte strings.

Problem

Unlike in Perl, there is currently no fast way in Ruby to do bitwise operations on byte strings. The bitwise-op methods #^, #!, #&, and #~ works only on numbers and not string.

Proposal

Implement String#^, #!, #&, and #~ in C.

Analysis

I think this is a low-impact change and mainly affect performance, because Ruby's String is a raw/byte string (not Unicode, etc). C implementation should be simple and straightforward. A couple of additional issues to consider though: 1) we can allow strings of different length to be XOR/AND/OR-ed. If the second string is shorter than the first, then we can just reuse/rollover to the beginning of the second string; 2) Ara T. Howard in ruby-talk suggested adding String#and!, #xor!, #not!, #or! too for in-place replacement.

Implementation

class String
  def ^(other)
    raise ArgumentError, "Can't bitwise-XOR a String with a non-String" \
      unless other.kind_of? String
    raise ArgumentError, "Can't bitwise-XOR strings of different length" \
      unless self.length == other.length
    result = (0..self.length-1).collect { |i| self[i] ^ other[i] }
    result.pack("C*")
  end
  def &(other)
    raise ArgumentError, "Can't bitwise-AND a String with a non-String" \
      unless other.kind_of? String
    raise ArgumentError, "Can't bitwise-AND strings of different length" \
      unless self.length == other.length
    result = (0..self.length-1).collect { |i| self[i] & other[i] }
    result.pack("C*")
  end
  def |(other)
    raise ArgumentError, "Can't bitwise-OR a String with a non-String" \
      unless other.kind_of? String
    raise ArgumentError, "Can't bitwise-OR strings of different length" \
      unless self.length == other.length
    result = (0..self.length-1).collect { |i| self[i] | other[i] }
    result.pack("C*")
  end
  def ~
    result = (0..self.length-1).collect { |i| ~ self[i] }
    result.pack("C*")
  end
end
ruby picture
Comments Current voting

two points:

  • how often do we need bit-wise string operation?
  • strings in Ruby2 will no longer be raw byte string. how can we define bit-wise operation on those?

-- matz.


Maybe it would be possible to have some sort of BitVector class that has these operations as part of the standard library for Ruby2? I'm also thinking that we should have a ByteString class because some uses of Ruby Strings take advantage of the fact that they are simply binary arrays (such as storing FXRuby icons as resource strings). -- Austin Ziegler


Thanks for the comments, matz. Since Ruby2 will have separate String and ByteString class, I still think we should add a pretty complete set of methods for ByteString, including bitwise operations. I don't know exactly how often we will use bitwise, but I think there will be uses in file processing, cryptography, and image processing. -- davegaramond


There is a library that I'm looking at implementing in Ruby that this would help with immensely (magic file detection, similar to libmmagic). -- Austin Ziegler


Strongly opposed 1
Opposed 7
Neutral 2
In favor 1
Strongly advocate 1
ruby picture
If you have registered at RCRchive, you may now sign in below. If you have not registered, you may sign up for a username and password. Registering enables you to submit new RCRs, and vote and leave comments on existing RCRs.
Your username:
Your password:

ruby picture

Powered by .