Bitwise question

A

Andrew Barringer

I'm working on a project that has a bitmap of permissions and I need to
find out if a user has access.=20

=20

Given permissions bit mask of 0001C0200F02000000000 where each bit
represents a specific permission

=20

And a request for permissions check on bits [37, 12, 48]

=20

What's the best way to find out if user has access to all requested
permissions?
 
P

Pascal J. Bourguignon

Andrew Barringer said:
I'm working on a project that has a bitmap of permissions and I need to
find out if a user has access.



Given permissions bit mask of 0001C0200F02000000000 where each bit
represents a specific permission



And a request for permissions check on bits [37, 12, 48]



What's the best way to find out if user has access to all requested
permissions?


(def check(permissions,bits)
(bits . inject(true) { | r , b |
(r and (0 != (permissions & (1 << b))))
})
end)
nil
(check 0xf0,[1,4,5,6]) -> false
(check 0xf0,[4,5,6]) -> true
 
R

Rob Biedenharn

Andrew Barringer said:
I'm working on a project that has a bitmap of permissions and I
need to
find out if a user has access.



Given permissions bit mask of 0001C0200F02000000000 where each bit
represents a specific permission



And a request for permissions check on bits [37, 12, 48]



What's the best way to find out if user has access to all requested
permissions?


(def check(permissions,bits)
(bits . inject(true) { | r , b |
(r and (0 != (permissions & (1 << b))))
})
end)
nil
(check 0xf0,[1,4,5,6]) -> false
(check 0xf0,[4,5,6]) -> true

Or a simpler version:

class Integer
def as_bits
ary = []
(self.size*8).times {|i| ary.unshift(i) if self.nonzero?}
ary
end

def check_permissions(*bits)
bits.all? {|bit| self[bit].nonzero? }
end
end

irb> 0x0001C0200F02000000000.as_bits
=> [68, 67, 66, 57, 47, 46, 45, 44, 37]
irb> 0x0001C0200F02000000000.check_permissions 37, 12, 48
=> false
irb> 0x0001C0200F02000000000.check_permissions 37, 47, 57
=> true

And written in normal Ruby rather than LispRuby ;-)

-Rob

Rob Biedenharn http://agileconsultingllc.com
(e-mail address removed)
 
D

David A. Black

Hi --

Andrew Barringer said:
I'm working on a project that has a bitmap of permissions and I need to
find out if a user has access.



Given permissions bit mask of 0001C0200F02000000000 where each bit
represents a specific permission



And a request for permissions check on bits [37, 12, 48]



What's the best way to find out if user has access to all requested
permissions?


(def check(permissions,bits)
(bits . inject(true) { | r , b |
(r and (0 != (permissions & (1 << b))))
})
end)
nil
(check 0xf0,[1,4,5,6]) -> false
(check 0xf0,[4,5,6]) -> true

Possibly more efficient since it short-circuits on the first failed
bit:

def check(permissions,bits)
bits.all? {|bit| (permissions & 1 << bit).nonzero? }
end


David

--
David A. Black / Ruby Power and Light, LLC
Ruby/Rails consulting & training: http://www.rubypal.com
Coming in 2009: The Well-Grounded Rubyist (http://manning.com/black2)

http://www.wishsight.com => Independent, social wishlist management!
 
A

Albert Schlef

Pascal said:
(def check(permissions,bits)
(bits . inject(true) { | r , b |
(r and (0 != (permissions & (1 << b))))
})
end)


That what happens when one spends his time typing parenthesis instead of
programming, my dear Pascal. I managed to count at least two bugs there.
One, you need to do (1 << (b-1)). Two, if you pass [] as the bits, the
result will be 'true'.
 
S

Stefan Rusterholz

Andrew said:
I'm working on a project that has a bitmap of permissions and I need to
find out if a user has access.



Given permissions bit mask of 0001C0200F02000000000 where each bit
represents a specific permission



And a request for permissions check on bits [37, 12, 48]



What's the best way to find out if user has access to all requested
permissions?

Whatever 'best' is supposed to mean. Here is one way:

requested_bits.all? { |bit| permissions[bit] == 1 }

Regards
Stefan
 
P

Pascal J. Bourguignon

Rob Biedenharn said:
(def check(permissions,bits)
(bits . inject(true) { | r , b |
(r and (0 != (permissions & (1 << b))))
})
end)
nil
Or a simpler version:

class Integer
def as_bits
ary = []
(self.size*8).times {|i| ary.unshift(i) if self.nonzero?}
ary
end

def check_permissions(*bits)
bits.all? {|bit| self[bit].nonzero? }
end
end


Simplier? A class, two methods, a lot of operations, a lot of memory!
 
P

Pascal J. Bourguignon

Albert Schlef said:
That what happens when one spends his time typing parenthesis instead of
programming, my dear Pascal. I managed to count at least two bugs there.
One, you need to do (1 << (b-1)).

Bit 0 is the first bit. 2^0 = 1
Two, if you pass [] as the bits, the
result will be 'true'.

Which is of course the correct answer.
All the bits in the empty set are in any bitfield.
There is no bit in the empty set hat are not in a given bitfield.
 
A

Albert Schlef

Pascal said:
Bit 0 is the first bit. 2^0 = 1

I stand corrected.
Two, if you pass [] as the bits, the
result will be 'true'.

Which is of course the correct answer.
All the bits in the empty set are in any bitfield.
There is no bit in the empty set hat are not in a given bitfield.

All right, all right, you win ;-) I now see that [].all? too returns
'true'.

(So my attempt at dissuading you from using parenthesis failed
miserably. Say, won't you consider dropping them for humanitarian
reasons?)
 
D

David A. Black

Hi --

Andrew Barringer said:
I'm working on a project that has a bitmap of permissions and I need to
find out if a user has access.



Given permissions bit mask of 0001C0200F02000000000 where each bit
represents a specific permission



And a request for permissions check on bits [37, 12, 48]



What's the best way to find out if user has access to all requested
permissions?


(def check(permissions,bits)
(bits . inject(true) { | r , b |
(r and (0 != (permissions & (1 << b))))
})
end)
nil
(check 0xf0,[1,4,5,6]) -> false
(check 0xf0,[4,5,6]) -> true

Or a simpler version:

class Integer
def as_bits
ary = []
(self.size*8).times {|i| ary.unshift(i) if self.nonzero?}
ary
end

def check_permissions(*bits)
bits.all? {|bit| self[bit].nonzero? }
end
end


Thanks for the reminder about Integer#[], one of those cool Ruby
things that come back and re-surprise me with their coolness
occasionally :)


David

--
David A. Black / Ruby Power and Light, LLC
Ruby/Rails consulting & training: http://www.rubypal.com
Coming in 2009: The Well-Grounded Rubyist (http://manning.com/black2)

http://www.wishsight.com => Independent, social wishlist management!
 
D

David A. Black

Rob Biedenharn said:
What's the best way to find out if user has access to all requested
permissions?

(def check(permissions,bits)
(bits . inject(true) { | r , b |
(r and (0 != (permissions & (1 << b))))
})
end)
nil
Or a simpler version:

class Integer
def as_bits
ary = []
(self.size*8).times {|i| ary.unshift(i) if self.nonzero?}
ary
end

def check_permissions(*bits)
bits.all? {|bit| self[bit].nonzero? }
end
end


Simplier? A class, two methods, a lot of operations, a lot of memory!


as_bits is just there to provide information for the sake of
understanding the examples. check_permissions is Rob's answer to the
original question. It looks about as simple as it could be: very
idiomatic, clear, and concise.

If you don't like adding to Integer you can make it functional-style
by adding a second argument.


David

--
David A. Black / Ruby Power and Light, LLC
Ruby/Rails consulting & training: http://www.rubypal.com
Coming in 2009: The Well-Grounded Rubyist (http://manning.com/black2)

http://www.wishsight.com => Independent, social wishlist management!
 
D

David A. Black

Hi --

Pascal said:
Bit 0 is the first bit. 2^0 = 1

I stand corrected.
Two, if you pass [] as the bits, the
result will be 'true'.

Which is of course the correct answer.
All the bits in the empty set are in any bitfield.
There is no bit in the empty set hat are not in a given bitfield.

All right, all right, you win ;-) I now see that [].all? too returns
'true'.

I could imagine wanting to handle the [] case conservatively. If the
idea is to screen for permissions, and you want the default to be
rejecting the person, then you'd probably want to reject an empty set
of bits. [].all? does indeed always return true, so you'd have to do a
separate empty? test somewhere.


David

--
David A. Black / Ruby Power and Light, LLC
Ruby/Rails consulting & training: http://www.rubypal.com
Coming in 2009: The Well-Grounded Rubyist (http://manning.com/black2)

http://www.wishsight.com => Independent, social wishlist management!
 
C

Clifford Heath

David said:
Thanks for the reminder about Integer#[], one of those cool Ruby
things that come back and re-surprise me with their coolness
occasionally :)

Cool indeed... pity it doesn't take a range however:

9547[0..-1]
TypeError: can't convert Range into Integer

oops.
 
A

Andrew Barringer

Thanks guys, the answers provided contained what I was looking for. I =
had hacked together something that worked but seemed so un-ruby like. =
This is nice looking very fast code.
=20
Andy

________________________________

From: Clifford Heath [mailto:[email protected]]
Sent: Wed 1/28/2009 10:37 PM
To: ruby-talk ML
Subject: Re: Bitwise question


Thanks for the reminder about Integer#[], one of those cool Ruby
things that come back and re-surprise me with their coolness
occasionally :)

Cool indeed... pity it doesn't take a range however:

9547[0..-1]
TypeError: can't convert Range into Integer

oops.
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

No members online now.

Forum statistics

Threads
473,999
Messages
2,570,243
Members
46,836
Latest member
login dogas

Latest Threads

Top