You cannot select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

75 lines
2.1 KiB
CoffeeScript

isPowerOfTwo = (number) -> number != 0 and ((number & (number - 1)) == 0)
class Bitmask
constructor: (@handler, initialValue, initialOriginalValue) ->
@value = initialValue
@originalValue = initialOriginalValue
_getFlagValue: (flag) ->
if @handler.flagMap[flag]?
return @handler.flagMap[flag].value
else
throw new Error("No such flag exists.")
_getFlagInheritances: (flag) ->
if @handler.flagMap[flag]?
return @handler.flagMap[flag].inheritedFlags
else
throw new Error("No such flag exists.")
add: (flag) ->
flagValue = @_getFlagValue(flag)
flagInheritances = @_getFlagInheritances(flag)
if @originalValue?
@originalValue = @originalValue | flagValue
@value = @value | flagValue
for inheritance in flagInheritances
flagValue = @_getFlagValue(inheritance)
@value = @value | flagValue
remove: (flag) ->
flagValue = @_getFlagValue(flag)
flagInheritances = @_getFlagInheritances(flag)
if @originalValue?
@originalValue = @originalValue & ~flagValue
@value = @value & ~flagValue
for inheritance in flagInheritances
flagValue = @_getFlagValue(inheritance)
if @originalValue? and !(@originalValue & flagValue)
@value = @value & ~flagValue
has: (flag) ->
flagValue = @_getFlagValue(flag)
return !!(@value & flagValue)
getValue: ->
return @value
getOriginalValue: ->
return @originalValue
class BitmaskHandler
constructor: (flagMap) ->
@setFlagMap flagMap
setFlagMap: (flagMap) ->
# Sanity check
for flag, value of flagMap
if typeof value == "number"
# Encapsulate in an object...
value = {value: value}
flagMap[flag] = value
value.inheritedFlags ?= []
for inheritance in value.inheritedFlags
if inheritance not of flagMap
throw new Error("The #{flag} flag attempts to inherit the non-existent #{inheritance} flag.")
if not isPowerOfTwo value.value
throw new Error("The value for the #{flag} flag (#{value.value}) is not a power of two.")
@flagMap = flagMap
create: (initialValue = 0, initialOriginalValue) ->
instance = new Bitmask(this, initialValue, initialOriginalValue)
module.exports = (flagMap) -> new BitmaskHandler(flagMap)